C# : 調用C++動態庫(dll)

在實際軟件開發過程中,由于公司使用了多種語言開發,在C#中可能需要實現某個功能,而該功能可能用其他語言已經實現了,那么我們可以調用其他語言寫好的模塊嗎?還有就是,由于C#開發好的項目,我們可以利用reflector等反編譯工具反編譯出其源代碼,所以對于一些核心算法,我們不希望被別人知道,因此為了增強代碼的安全性,我們需要將一些核心算法用C或C++來編寫,然后用C#來調用這些已經寫好的接口。在面對以上情況時,我們該怎么做呢?


?方案一:重新實現
??????? 針對第一種情況,我們可以將C或者C++功能用C#來重新實現,這樣的話代碼比較統一,維護比較方便,但是這樣的話增加了軟件開發的成本,把C++的代碼功能改成C#涉及到指針和內存的操作比較繁瑣,況且有開發好的模塊為什么不重復利用呢?針對第二種情況就不能得到有效解決,雖然可以使用混淆器對代碼進行混淆,但是任然不是很安全。

?方案二:封裝COM組件
??????? 我們可以將C或者C++的函數封裝成COM組件,在C#中調用時比較方便,但是COM組件需要注冊,而且多次注冊可能也會導致一些問題,同時在處理C或者C++的類型與COM組件的類型轉換的時候也可能有些麻煩。


?方案三:使用動態鏈接庫
??????? 我們可以直接調用C或者C++已經寫好的動態鏈接庫,這樣比較方便,這樣很好的解決了上述問題。

?

??????? 在實際項目中,我們需要使用C#調用C++的一些接口,因此我使用的是方案三采用動態庫,下面我就在實際中怎么處理的進行說明。
?????? ?在調用動態庫的過程中我也遇到了以下一些問題:
????????1、C++中有指針,C#中需要使用指針嗎?
????????由于C++中的動態庫中有指針參數,因此我也是用.NET的不安全代碼,使用了C#的指針,但是最后也還是出現了一些問題,如在C#中傳入的參數是一個二維數組時就出現了問題,這個問題我在網上找了好多資料也沒有解決,最后和c++程序員商量了下改變了傳入參數的參數類型。最后也沒有使用指針。
????????2、C#和C++中的類型如何轉換呢?
??????? 雖然C#和C++比較類似,但是其給我們的參數類型我們要與C#的參數類型一一對應起來,因此我找了一些資料把其類型一一對應了,具體看后續說明。
????????3、C++寫好的動態庫放到那個位置呢?
????????關于C++動態庫的位置也是個問題,在應用中我們使用了相對路徑和絕對路徑進行測試,有的發現在VS中可以調用到,但是發布后發現無法調用到動態庫,最后只要把動態的dll放到系統的目錄system32下面才解決了改問題,目前還沒找到其他的方法,如有其他的更好方法還請大家指點。
????????4、如何反編譯C++的dll的名稱,端口?
??????? 可以通過Dependency Walker工具進行反編譯查看別人寫的動態庫的信息
????????5、還有其他的一些細節,如C#調用動態庫需要指定其編碼、代碼寫法等等

c#調用c++動態庫一般我們這樣寫

[DllImport("UCamer.dll", CallingConvention = CallingConvention.Winapi)]
public extern static void Disp_Destroy(IntPtr hShow);
DllImport的第一個參數UCamer.dll是動態庫dll的路徑,此dll放在程序運行的根目錄或者c:windows/sytem32下

??CallingConvention 參數是c#調用c++的方式 是個枚舉 msdn解釋如下

  

Cdecl調用方清理堆棧。這使您能夠調用具有?varargs?的函數(如?Printf),使之可用于接受可變數目的參數的方法。?
FastCall不支持此調用約定。
StdCall被調用方清理堆棧。這是使用平臺 invoke 調用非托管函數的默認約定。?
ThisCall第一個參數是?this?指針,它存儲在寄存器 ECX 中。其他參數被推送到堆棧上。此調用約定用于對從非托管 DLL 導出的類調用方法。?
Winapi此成員實際上不是調用約定,而是使用了默認平臺調用約定。例如,在 Windows 上默認為?StdCall,在 Windows CE.NET 上默認為?Cdecl。?

?從上面來看Winapi方式是根據系統自動選擇調用規約的。 而thisCall是對c++類的調用方法。 所以 一般情況下我們選擇Winapi就可以了。

例子:

#region 無標題窗體右鍵任務欄彈出菜單代碼[DllImport("user32.dll", EntryPoint = "GetWindowLong", CharSet = CharSet.Auto)]public static extern int GetWindowLong(HandleRef hWnd, int nIndex);[DllImport("user32.dll", EntryPoint = "SetWindowLong", CharSet = CharSet.Auto)]public static extern IntPtr SetWindowLong(HandleRef hWnd, int nIndex, int dwNewLong);protected override CreateParams CreateParams{get{const int WS_MINIMIZEBOX = 0x00020000;  // Winuser.h中定義   CreateParams cp = base.CreateParams;cp.Style = cp.Style | WS_MINIMIZEBOX;   // 允許最小化操作   return cp;}}#endregion#region 窗體拖動代碼[DllImport("user32.dll")]public static extern bool ReleaseCapture();[DllImport("user32.dll")]public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);public const int WM_SYSCOMMAND = 0x0112;public const int SC_MOVE = 0xF010;public const int HTCAPTION = 0x0002;private void Login_MouseDown(object sender, MouseEventArgs e){ReleaseCapture();SendMessage(this.Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);}#endregion[DllImport("wininet.dll")]private extern static bool InternetGetConnectedState(out int conn, int val);private void btnNetTest_Click(object sender, EventArgs e){int Out;if (InternetGetConnectedState(out Out, 0) == true){MessageDxUtil.ShowTips("Internet網絡連通!");}else{MessageDxUtil.ShowTips("Internet網絡不通!");}}

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/252101.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/252101.shtml
英文地址,請注明出處:http://en.pswp.cn/news/252101.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python3.5以上版本lxml導入etree報錯Unresolved reference

Web抓取Web站點使用HTML描述,這意味著每個web頁面是一個結構化的文檔。有時從中 獲取數據同時保持它的結構是有用的。web站點不總是以容易處理的格式, 如 csv 或者 json 提供它們的數據。 這正是web抓取出場的時機。Web抓取是使用計算機程序將web頁面數據…

linux設置history歷史記錄

#說明export HISTSIZE1000 #設置歷史記錄顯示1000行export HISTTIMEFORMAT%F %T #設置歷史記錄格式 999 2017-08-15 10:58:32 #修改vim /etc/profilesed -i "s/\(HISTSIZE\).*/\11000/" /etc/profilesed -i "/HISTSIZE/aexport HISTTIMEFORMAT%F %T " /et…

STL-容器庫101--array【C11】

1. 原型 C11提供 template < class T, size_t N > class array;T&#xff1a; 元素類型&#xff0c;以 array::value_type 作為別名使用&#xff1b;N&#xff1a; array中元素大小&#xff1b; 固定size的序列容器&#xff1b;初始化時&#xff0c; array對象不保存任何…

C#:向C++封送結構體數組

在使用第三方的非托管API時&#xff0c;我們經常會遇到參數為指針或指針的指針這種情況&#xff0c; 一般我們會用IntPtr指向我們需要傳遞的參數地址&#xff1b; 但是當遇到這種一個導出函數時,我們如何正確的使用IntPtr呢&#xff0c; extern "C" __declspec(dll…

其它綜合-CentOS7 忘記root密碼

CentOS7 忘記root密碼 長時間不用的 CentOS 機器再次開機的時候忽然忘記了密碼&#xff0c;總不能就重裝一臺吧&#xff0c;還有好多服務在機器上&#xff0c;于是決定重置root的密碼。   如果是已經開啟的機器&#xff0c;需要進行關閉&#xff0c;重新啟動。在啟動選擇內核…

left join on and 與 left join on where的區別

數據庫在通過連接兩張或多張表來返回記錄時&#xff0c;都會生成一張中間的臨時表&#xff0c;然后再將這張臨時表返回給用戶。 在使用left jion時&#xff0c;on和where條件的區別如下&#xff1a; 1、 on條件是在生成臨時表時使用的條件&#xff0c;它不管on中的條件是否為真…

spring boot高性能實現二維碼掃碼登錄(中)——Redis版

前言 本打算用CountDownLatch來實現&#xff0c;但有個問題我沒有考慮&#xff0c;就是當用戶APP沒有掃二維碼的時候&#xff0c;線程會阻塞5分鐘&#xff0c;這反而造成性能的下降。好吧&#xff0c;現在回歸傳統方式&#xff1a;前端ajax每隔1秒或2秒發一次請求&#xff0c;去…

C# :socket 通訊基礎使用實例

們在講解Socket編程前&#xff0c;先看幾個和Socket編程緊密相關的概念&#xff1a; TCP/IP層次模型當然這里我們只討論重要的四層 01&#xff0c;應用層(Application)&#xff1a;應用層是個很廣泛的概念&#xff0c;有一些基本相同的系統級TCP/IP應用以及應用協議&#xff0…

IBM發表論文:可能已找到處理量子計算退相干的方法

在《自然》雜志最近發表的一篇論文中&#xff0c;IBM和其他機構的研究人員設計了兩種量子算法&#xff0c;利用變分量子電路和量子核估計器來訓練一種支持向量機分類器。這兩種算法背后的關鍵思想是使用量子狀態空間作為特征空間表示&#xff0c;有效地構建映射&#xff0c;從原…

PHP + NGINX 控制視頻文件播放,并防止文件下載

最簡單的方法是使用NGINX的 internal 功能 server { listen 80; server_name www.xxx.com;  location / { index index.php index.html index.htm; root /xxx; if (!-e $request_filename) { rewrite ^/index.php(.*)$ /index.php?s$…

可視化調試工具

rosrun rqt_console rqt_console # 查看日志消息&#xff0c;可filter、highlight指定級別。 rosrun rqt_logger_level rqt_logger_level # 可設在日志記錄器的嚴重級別 rosrun rqt_topic rqt_topic # 顯示topic調試信息 rosrun rqt_publisher rqt_publisher # 在界面中管理ro…

C#:委托基礎與事件

通過以下思維導圖&#xff0c;學習委托的基本概念&#xff0c;后面著重講解委托的運用&#xff0c;希望通過最簡單的方式收獲更多的知識。 1.委托的各種寫法 1、委托 委托名new 委托&#xff08;會調用的方法名); 委托名&#xff08;參數&#xff09;; 2、委托 委托名 會調用…

Git Bash關鍵命令

1.默認目錄是C:\Users\用戶名 2.切換目錄&#xff1a;$cd c:\\windows 3.切換到上級目錄&#xff1a;cd ..&#xff0c;中間有空格 4.列出某目錄所有文件&#xff0c;相當于DOS下的dir&#xff1a;ls c:\\windows 5.查看配置信息&#xff1a;git config --list 以下是顯示信息 …

C#:invoke 與 BeginInvoke使用區別

invoke和begininvoke 區別 一直對invoke和begininvoke的使用和概念比較混亂&#xff0c;這兩天看了些資料&#xff0c;對這兩個的用法和原理有了些新的認識和理解。 首先說下&#xff0c;invoke和begininvoke的使用有兩種情況&#xff1a; 1. control中的invoke、begininvoke。…

Django基本命令

Django基本命令 1.創建一個Django 項目 django_admin.py startproject mysite當前目錄下會生成mysite的工程&#xff0c;目錄結構如下&#xff1a; manage.py ----- Django項目里面的工具&#xff0c;通過它可以調用django shell和數據庫等。settings.py ---- 包含了項目的默認…

Git忽略規則.gitignore梳理

對于經常使用Git的朋友來說&#xff0c;.gitignore配置一定不會陌生。廢話不說多了&#xff0c;接下來就來說說這個.gitignore的使用。首先要強調一點&#xff0c;這個文件的完整文件名就是".gitignore"&#xff0c;注意最前面有個“.”。 一般來說每個Git項目中都需…

第二周CoreIDRAW課總結

1.這節課學到了什么知識&#xff1f; 學到了圖像的復制&#xff0c;再制鼠標復制&#xff0c;重復&#xff0c;還有對象的對齊&#xff0c;對象的分布順序。 2.有哪些心得體會&#xff1f; 做了課本的練習&#xff0c;會用窗口里面的泊塢窗造型命令也作出了一個作品。 3.這節課…

axios關于針對請求時長策略設計的思考

前言 在我們的業務請求中&#xff0c;有很多時候會針對有不同時長的需求策略性設置。這里針對這個需求進行詳細的展開。 針對這種情況&#xff0c;我們的timout的一般是根據請求地址來的&#xff0c;所以核心處理技巧便是如何根據不同的request地址去設置不同的timeout. 我們之…

C#:WinForm無邊框窗體移動方法、模仿鼠標單擊標題欄移動窗體位置

方法一&#xff1a;直接通過修改窗體位置從而達到移動窗體的效果 方法二&#xff1a;直接偽裝發送單擊任務欄消息&#xff0c;讓應用程序誤以為單擊任務欄從而移動窗體 方法一 1.定義一個位置信息Point用于存儲鼠標位置 private Point mPoint; 2.給窗體等控件增加MouseDown…

Python 字典刪除元素clear、pop、popitem

同其它python內建數據類型一樣&#xff0c;字典dict也是有一些實用的操作方法。這里我們要說的是字典刪除方法&#xff1a;clear()、pop()和popitem()&#xff0c;這三種方法的作用不同&#xff0c;操作方法及返回值都不相同。接下來就來查看下這些字典特定方法的具體用法是什么…