C#委托實現C++ Dll中的回調函數

from:https://blog.csdn.net/ferrycooper/article/details/63261771

很多的Dll都是CC++寫的,那么如果C#想要調用Dll中的函數怎么辦,尤其是Dll函數其中一個參數是函數指針的,即里面有回掉函數的用C#怎么實現?

C中的回掉函數在C#中有中特殊的處理方式叫委托,即要實現的回掉函數委托給另一個和它返回值類型以及函數參數類型、數量一樣的方法來實現。


一、新建項目Visual C++??Win32控制臺應用,工程名為CcreateDll,解決方案名為Dlltest

?

確定—>下一步

?

?

應用程序類型選Dll>完成

?

新建頭文件Ccreate.h,聲明導出函數,其中API_DECLSPEC?int?CallPFun(addP?callback,?inta,?int?b)?第一個參數為函數指針,內容如下:

?

[cpp]?view plain?copy
  1. #pragma?once??
  2. ??
  3. #ifndef?Ccreate_H_??
  4. #define?Ccreatel_H_??
  5. ??
  6. typedef??int(*addP)(int,?int);??
  7. ??
  8. #ifdef?_EXPORTING???
  9. #define?API_DECLSPEC?extern?"C"?_declspec(dllexport)???
  10. #else???
  11. #define?API_DECLSPEC??extern?"C"?_declspec(dllimport)???
  12. #endif??
  13. ??
  14. API_DECLSPEC?int?Add(int?plus1,?int?plus2);??
  15. API_DECLSPEC?int?mulp(int?plus1,?int?plus2);??
  16. API_DECLSPEC?int?CallPFun(addP?callback,?int?a,?int?b);??
  17. ??
  18. #endif??

頭文件有了,在CcreateDll.cppinclude頭文件,并實現相關函數。Ccreate.cpp如下

?

[cpp]?view plain?copy
  1. //?CcreateDll.cpp?:?定義?DLL?應用程序的導出函數。??
  2. //??
  3. ??
  4. #include?"stdafx.h"??
  5. #include?<iostream>???
  6. #include?"Ccreate.h"??
  7. ??
  8. using?namespace?std;??
  9. ??
  10. int?Add(int?plus1,?int?plus2)??
  11. {??
  12. ????int?add_result?=?plus1?+?plus2;??
  13. ????return?add_result;??
  14. }??
  15. int?mulp(int?plus1,?int?plus2)??
  16. {??
  17. ????int?add_result?=?plus1?*?plus2;??
  18. ????return?add_result;??
  19. }??
  20. ??
  21. int?CallPFun(int(*callback)(int,?int),?int?a,?int?b)?{??
  22. ????return?callback(a,?b);??
  23. }??

函數CallPFun實際就是傳入函數指針及其參數,內部直接調用函數指針。

Release模式下生成CcreateDll工程

?

生成成功后在解決方案目錄的Release文件夾下會看到生成的CcreateDll.dll,使用Dll查看工具可以看到三個導出函數。

?

二、新建C#控制臺工程CsharpCallDll實現調用Dll并使用委托實現回掉。

?

?

CsharpCallDll工程Program.cs如下:

?

[csharp]?view plain?copy
  1. using?System;??
  2. using?System.Collections.Generic;??
  3. using?System.Linq;??
  4. using?System.Text;??
  5. using?System.Threading.Tasks;??
  6. using?System.Runtime.InteropServices;??
  7. ??
  8. namespace?CsharpCallDll??
  9. {??
  10. ????public?class?Program??
  11. ????{??
  12. ????????[UnmanagedFunctionPointer(CallingConvention.Cdecl)]??
  13. ????????public?delegate?int?DllcallBack(int?num1,?int?num2);??
  14. ??
  15. ????????[DllImport(@"../../../Release/CcreateDll.dll",?EntryPoint?=?"Add",?SetLastError?=?true,?CharSet?=?CharSet.Ansi,?ExactSpelling?=?false,?CallingConvention?=?CallingConvention.Cdecl)]??
  16. ????????extern?static?int?Add(int?a,?int?b);??
  17. ??
  18. ????????[DllImport(@"../../../Release/CcreateDll.dll",?EntryPoint?=?"mulp",?SetLastError?=?true,?CharSet?=?CharSet.Ansi,?ExactSpelling?=?false,?CallingConvention?=?CallingConvention.Cdecl)]??
  19. ????????extern?static?int?mulp(int?a,?int?b);??
  20. ??
  21. ????????[DllImport(@"../../../Release/CcreateDll.dll",?EntryPoint?=?"CallPFun",?SetLastError?=?true,?CharSet?=?CharSet.Ansi,?ExactSpelling?=?false,?CallingConvention?=?CallingConvention.Cdecl)]??
  22. ????????public?extern?static?int?CallPFun(DllcallBack?pfun,?int?a,?int?b);??
  23. ????????//[MarshalAs(UnmanagedType.FunctionPtr)]??
  24. ????????static?void?Main(string[]?args)??
  25. ????????{??
  26. ????????????int?a?=?3;??
  27. ????????????int?b?=?4;??
  28. ????????????int?result;??
  29. ????????????DllcallBack?mycall;??
  30. ????????????mycall?=?new?DllcallBack(Program.CsharpCall);??
  31. ????????????result?=?Add(a,?b);??
  32. ????????????Console.WriteLine("Add?返回{0}",?result);??
  33. ????????????result?=?mulp(a,?b);??
  34. ????????????Console.WriteLine("mulp?返回{0}",?result);??
  35. ????????????result?=?CallPFun(mycall,?a,?b);??
  36. ????????????Console.WriteLine("dll回掉?返回{0}",?result);??
  37. ????????????Console.ReadLine();??
  38. ????????}??
  39. ??
  40. ????????public?static?int?CsharpCall(int?a,?int?b)??
  41. ????????{??
  42. ????????????return?a?*?a?+?b?*?b;??
  43. ????????}??
  44. ????}??
  45. }??

????

通過DllImport導入相應的Dll并聲明Dll中的導出函數,CcreateDll.dll中導出函數CallPFun有三個參數,原型為

?

[cpp]?view plain?copy
  1. int?CallPFun(int(*callback)(int,?int),?int?a,?int?b)?{??
  2. ????return?callback(a,?b);??
  3. ???}??
???

參數1為一個帶兩個int參數的返回值為int型的函數指針,這里聲明一個委托

public?delegate?int?DllcallBack(int?num1,?intnum2);

該委托可以指向任何帶兩個int型參數且返回值為int型的方法,這里的CsharpCall方法可以看作是回掉函數的實現。

?

[csharp]?view plain?copy
  1. public?static?int?CsharpCall(int?a,?int?b)??
  2. ???{??
  3. ????????????return?a?*?a?+?b?*?b;??
  4. ???}??
???

通過????????DllcallBack?mycall;

???????????mycall =?new?DllcallBack(Program.CsharpCall);

??把實際要完成的工作交給CsharpCall去完成。

????運行CsharpCallDll,結果如下:

??

?

是不是實現了C#委托實現回掉

?

最后還有如果聲明委托時在public delegate int DllcallBack(int num1, int num2);上面沒有[UnmanagedFunctionPointer(CallingConvention.Cdecl)]這一句,那么運行時將會出現System.AccessViolationException異常,如下

?

?

還有Dll調用約定,CallingConvention.有五種調用方式

CallingConvention= CallingConvention.StdCall

CallingConvention= CallingConvention.Cdecl

CallingConvention= CallingConvention.FastCall

CallingConvention= CallingConvention.ThisCall

CallingConvention= CallingConvention.Winapi

到底使用哪種方式,網上有說"Bydefault, C and C++ use cdecl - but marshalling uses stdcall to match theWindows API."即默認情況下,CC++使用的Cdecl調用,但編組使用StdCall調用匹配的Windows API,對于FastCallThisCallWinapi這三種調用方式尚不清楚。

這里將CallingConvention= CallingConvention.Cdecl改成CallingConvention = CallingConvention.StdCall,重新運行導致堆棧不對稱如下

?



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

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

相關文章

安裝Birt方法

安裝BIRT 方法&#xff1a; 博客地址&#xff1a;http://www.mamicode.com/info-detail-850588.html 注意&#xff1a;在 Install new Software 中輸入地址&#xff1a;http://download.eclipse.org/birt/update-site/4.2-interim 看好了 出來的四項要全部選中 &#xff0c;然后…

iOS NSString和NSDate轉換

后臺返回的時間字符串不是標準的時間而是計算機時間的時候&#xff0c;我們需要將它們轉換為標準時間&#xff0c;再進行轉換。 //字符串轉為時間&#xff0c;時間格式自己定 NSString * time "1501776000"; //時間字符串 NSInteger num [time integerValue]; …

15個最好的HTML5前端響應式框架(2014)

文中的多個框架基于SASS創建&#xff0c;SCSS是一種比LESS更簡潔的樣式表編程語言&#xff0c;它能夠編繹成CSS&#xff0c;可復用CSS代碼&#xff0c;聲明變量&#xff0c;甚至是函數&#xff0c;類Ruby/Python的語法。參見&#xff1a; LESS vs SASS&#xff1f;選擇哪種CSS樣…

DLL導出類和導出函數

from:https://blog.csdn.net/goodluckmt/article/details/526912971、動態庫DLL中的類或者函數有時候要被其他的庫調用&#xff0c;因此需要被其他庫調用的類或者函數需要進行導出。 2、首先編寫需要導出的DLL&#xff0c;新建一個工程設置應用程序類型為DLL3、類的代碼如下 頭…

Nginx做web服務器linux內核參數優化

Nginx做web服務器linux內核參數優化Nginx提供web服務時Linux內核參數調整是必不可少的&#xff0c;其中在優化方面就需要我們格外的注意。在下面就是對Linux內核參數優化的詳細介紹&#xff0c;希望大家有所收獲。關于Linux內核參數的優化&#xff1a;net.ipv4.tcp_max_tw_buck…

iOS系統發布時間

發布日期 版本編號 更改2017年9月12日 iOS11 GM seed2017年6月19日 iOS10.3.32016年11月9日 iOS10.2 Beta2 發布iOS10.2測試版版2016年11月1日 iOS10.2 Beta1 發布iOS10.2測試版版2016年10月25日 iOS10.1 發布iOS10.1正式版2016年9月22日 iOS10.1 Beta 發布iOS10.1測試版2016年…

Tomacat服務器的安裝和配置

一&#xff0c; Tomcat服務器的下載地址(Apache Tomcat的官網): http://tomcat.apache.org/download-70.cgi 這里為了穩定性安裝的版本為7.0. 截止目前版本已經發行到了9.0. 二&#xff0c; 解壓下載的壓縮包之后直接進入傻瓜式的安裝。   下載文件的全名&#xff1a; apach…

函數指針與回調函數詳解

函數指針與回調函數詳解 1.什么是函數指針&#xff1f; 函數&#xff08;的&#xff09;指針就是指針。這個指針存放一個函數的地址&#xff0c;而函數的名稱就該函數的入口&#xff0c;即地址。這類似于數組名就是數組的首地址。我們可以通過反匯編直觀的查看到函數名和函數地…

【轉載】Direct3D基礎知識

原文&#xff1a;Direct3D基礎知識 重新從頭開始學習DX,以前太急于求成了,很多基礎知識都沒掌握就開始寫程序了,結果出了問題很難解決.1. D3D體系結構D3D與GDI處與同一層次,區別在于,D3D可以使用HAL(Hardware Abstraction Layer)通過DDI來訪問圖形硬件,充分發揮硬件性能.…

翻譯:程序員數據結構基礎:選擇正確的數據結構

本文轉載自GameDev.net&#xff0c;僅供學習交流。因為剛剛開始學習翻譯&#xff0c;難免有些疏漏&#xff0c;如果有哪些地方翻譯的不正確&#xff0c;請不吝告知&#xff0c;萬分感謝。 原文鏈接&#xff1a;http://www.gamedev.net/page/resources/_/technical/general-prog…

關于Xcode隱藏打印的logs的方法

https://www.cnblogs.com/jukaiit/p/5881062.html 第一步&#xff1a; 第二步&#xff1a; 第三步&#xff1a; 添加參數&#xff1a; Name &#xff1a;OS_ACTIVITY_MODE Value : disable

指針函數與函數指針的區別

首先它們之間的定義&#xff1a;1、指針函數是指帶指針的函數&#xff0c;即本質是一個函數&#xff0c;函數返回類型是某一類型的指針。 類型標識符 *函數名(參數表)int *f(x&#xff0c;y);首先它是一個函數&#xff0c;只不過這個函數的返回值是一個地址值。函數返回值必須用…

數組字典

#import <Foundation/Foundation.h>int main(int argc, const char * argv[]) {autoreleasepool { //把字典放到數組中NSDictionary *dic1{"name":"小明","class":"IOS8","age":"22"};NSDictionary *dic2{&…

C++走向遠洋——63(項目二2、兩個成員的類模板)

*/ * Copyright (c) 2016&#xff0c;煙臺大學計算機與控制工程學院 * All rights reserved. * 文件名&#xff1a;text.cpp * 作者&#xff1a;常軒 * 微信公眾號&#xff1a;Worldhello * 完成日期&#xff1a;2016年6月4日 * 版本號&#xff1a;V1.0 * 問題描述&…

iOS 抓包工具 charles工具

在Charles官網下載最新的 安裝包 在電腦上安裝完成之后&#xff0c;以 注冊碼 Registered Name: https://zhile.io License Key: 48891cf209c6d32bf4 進行注冊即可完成 在手機上面設置代理&#xff1a;輸入電腦的網絡IP以及端口號 以下為查找的步驟&#xff1a; 在手機上手…

指針數組與數組指針詳解

指針數組與數組指針詳解 1.什么是指針數組和數組指針&#xff1f; 指針數組&#xff1a;指針數組可以說成是”指針的數組”&#xff0c;首先這個變量是一個數組&#xff0c;其次&#xff0c;”指針”修飾這個數組&#xff0c;意思是說這個數組的所有元素都是指針類型&#xff0…

寫一個Android輸入法01——最簡步驟

本文演示用Android Studio寫一個最簡單的輸入法。界面和交互都很簡陋&#xff0c;只為剔肉留骨&#xff0c;彰顯寫一個Android輸入法的要點。 1、打開Android Studio創建項目&#xff0c;該項目和普通APP的不同之處在于它不需要添加任何Activity&#xff1a;我給該輸入法命名為…

句柄與指針的區別

句柄實際上是一種指向某種資源的指針&#xff0c;但與指針又有所不同&#xff1a;指針對應著一個數據在內存中的地址&#xff0c;得到了指針就可以自由地修改該數據。 Windows并不希望一般程序修改其內部數據結構&#xff0c;因為這樣太不安全。所以Windows給每個使用GlobalAll…

iOS 11 適配

http://blog.csdn.net/st646889325/article/details/79066361 這一個不錯的文章

談談自己對于Auth2.0的見解

Auth的原理網上有很多&#xff0c;我這里就不在贅述了。 這里有張時序圖我個人覺得是比較合理而且直觀的&#xff0c;&#xff08;感謝這篇博文&#xff1a;http://justcoding.iteye.com/blog/1950270&#xff09; 參照這個流程&#xff0c;模擬了下部分代碼&#xff0c;當然是…