0 前言
應老板的要求,寫一個二維碼生成軟件。從后台條碼生成(C\C++語言),到前天界面(winform)。期間遇到不少問題,這里打算把整個流程及遇到的問題一一分享,給初學者一個從源碼到客戶可以安裝運行有一個整體的感性認識,同時給繼續在C#調用非托管動態鏈接庫Dll及部署時提示找不到dll而出錯的后來者提供參考。
1、條碼生成
該部分采用C、C++混合寫的。原本是有main()函數,可以測試運行的。保存圖片用到了opencv的庫函數,這點可要注意了,再發布部署整個程序要一同包括用到的opencv的庫。在VC++6.0 上,將用到的接口封裝了一下並導出dll庫。
2、界面
根據dll接口及需求用C# winform 做了個界面。在界面程序中調用dll文件時遇到了問題。
2.1 C#如何調用非托管dll
具體的可參加網上的例子。主要說明如下:
a.[DllImport(dllname)]聲明必須時必須指明調用入口EntryPoint(具體屬性設置參加網絡資源),該聲明放在欲調用的函數前面,如果該dll中導出了多個函數入口,需要對每個函數分別聲明。
b.C\C++和C#之間的類型轉換問題。這個問題在dll聲明待調用函數時,要求已經轉為為C#的變量類型。比如在C++正const char*,在這里要轉為為string等。具體網絡資源。
c.找不到*.dll文件。這是C#調用非托管dll最常見的問題了。可能的原因之一,就是dll聲明函數類型不匹配,具體解決如上述b中的介紹。原因之二,dll文件放置位置的問題。具體分析如下:
DLL文件必須位於程序當前目錄或系統定義的查詢路徑中。(.exe所在位置;system32下;添加引用;實驗所得,對於非托管只能放在system32下才有效果,具體分析見下文。)
DLLImport會按照順序去查找DLL文件(程序當前目錄>System32目錄>環境變量Path所設置路徑)。
返回類型變量、方法名稱、參數列表一定要與DLL文件中的定義相一致。
注:首先需要確認引用了哪些組件?哪些是托管的?那些是非托管的?托管的很方便,直接被使用的需要引用,間接使用的需要拷貝到Bin目錄下。非托管的就特殊處理(實際上你拷貝到bin是沒有任何作用的,因為CLR會把文件拷貝到一個臨時目錄下,然后在那運行Web,而CLR只會拷貝托管文件,這就是為什么把非托管的DLL放到bin目錄下仍然提示找不到該模塊)。解決方案:首先在服務器上建立一個新建的目錄,假設是(C:\ProgramDir\WinDLL\).然后在環境變量中,給Path變量添加這個目錄,最后把非托管的DLL文件都拷貝到該目錄下。或者更干脆把DLL放到System32目錄中。對於自己部署的應用程序,這樣的確能很好的解決問題。然而如果我們用的是虛擬空間,我們有沒有辦法吧注冊Path變量或者把我們自己的DLL拷貝System32目錄下
3 打包部署
具體參見:http://blog.163.com/cgz2010@126/blog/static/168179141201132402919175/
http://blog.163.com/huhenggang@126/blog/static/113852947201132194469/
4 部署安裝
常見問題是找不到dll文件。在第2部分“如何調用非托管dll”時已近做了說明,而將所需的dll放大system32下,運行還是出錯提示找不到dll。這是可能的原因是你添加的dll文件還依賴其他dll文件,所以請用相關工具分析該dll文件的依賴,然后一同拷貝到system32下即可。我是這樣解決的。
參考:http://www.cnblogs.com/easirm/archive/2010/05/11/net_easirm.html
http://blog.csdn.net/jame_peng/article/details/4387906
http://topic.csdn.net/u/20100804/09/9f1b108c-b760-4814-9620-8b40ef08b85e.html
http://topic.csdn.net/u/20120220/13/ded0ad81-8ee9-40cc-8b66-ceccf546a1df.html