如何在非托管C++中调用托管C#中的回调函数
2016-06-16 09:09
791 查看
如何在非托管C++中调用托管C#中的回调函数 [问题点数:40分,结帖人kndyc]
不显示删除回复 显示所有回复显示星级回复 显示得分回复
只显示楼主
收藏
关注 kndyc kndyc 等级: 结帖率:100% | 楼主发表于: 2012-12-08 10:46:02 大家好,我刚刚接触.net,下面是msdn关于回调函数的解释 http://msdn.microsoft.com/zh-cn/library/843s5s5x(v=vs.100).aspx 问题是如何在非托管C++中调用托管C#中的回调函数,文章中没有说。 为了防止垃圾回收,我用HandleRef盯住了回调函数,当C#程序执行了 CallBack myCallBack = new CallBack(EnumReportApp.Report); IntPtr ptr = Marshal.GetFunctionPointerForDelegate(myCallBack); HandleRef hr = new HandleRef(myCallBack, ptr); EnumWindows(hr, 0); 之后,myCallBack的指针被传递到了C++,假设指针的形参名是pCallBack,在C++的DLL中直接执行 pCallBack(); 然后程序抛出了异常:“访问了受保护的内存区域”,继续运行抛出“回调函数被垃圾回收”。 我觉得应该是C++调用C#的函数指针的方法不对,请大家看看问题出在哪里? 更多0分享到: 相关主题推荐: c++ 指针 callback library 异常 相关帖子推荐: 在将 varchar 值 '交易案例' 转换成数据类型 int 时失败。 如何让其它程序报错 C#求一算法 请教一个指针的指针做形参的问题 C#获取JavaScript中的数据 菜鸟求助,c++指针问题 用c程序写的socket下载网页,有个url的网页死活下不下来 关于类默认构造函数的一些问题,求助。 |
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理 回复次数:18 |
关注 wei_hang 我不是李白 等级: | #1 得分:0回复于: 2012-12-08 10:48:27 C++函数指针对应C#委托 |
CSDN投诉事项说明 对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理 |
关注 kndyc kndyc 等级: | #2 得分:0回复于: 2012-12-08 11:00:53 C++函数指针对应C#委托,怎么对应呢? |
【社区之星】朱燚:转战传统应用的弄潮儿 对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理 |
关注 hdt 倦怠 等级: | #3 得分:10回复于: 2012-12-08 11:03:15 全部折叠全部展开 代码:全部 代码:多个 代码:Visual Basic 代码:C# 代码:Visual C++ 代码:J# 代码:JScript Visual Basic C# Visual C++ J# JScript .NET Framework 开发人员指南 Callback 示例 请参见 发送反馈意见 该示例说明如何将委托传递给需要函数指针的非托管函数。委托是可以容纳对方法的引用的类,并且等效于类型安全函数指针或回调函数。 注意: 当您在调用内部使用委托时,公共语言运行库将在该调用的持续时间内防止对委托执行垃圾回收。但是,如果非托管函数存储该委托以供在该调用完成后使用,则您必须手动防止进行垃圾回收,直到非托管函数完成对该委托的使用为止。有关更多信息,请参见 HandleRef 示例和 GCHandle 示例。 Callback 示例使用以下非托管函数(这里同时显示其原始函数声明): 从 PinvokeLib.dll 导出的 TestCallBack。 复制代码 void TestCallBack(FPTR pf, int value); 从 PinvokeLib.dll 导出的 TestCallBack2。 复制代码 void TestCallBack2(FPTR2 pf2, char* value); PinvokeLib.dll 是一个自定义非托管库,它包含前面列出的函数的实现。 在该示例中,LibWrap 类包含 TestCallBack 和 TestCallBack2 方法的托管原型。这两个方法都将委托作为参数传递给回调函数。该委托的签名必须与它所引用的方法的签名相匹配。例如,FPtr 和 FPtr2 委托的签名与 DoSomething 和 DoSomething2 方法的签名相同。 下面的代码示例的源代码由 .NET Framework 平台调用技术示例 提供。 声明原型 Visual Basic 复制代码 Public Delegate Function FPtr( ByVal value As Integer ) As Boolean Public Delegate Function FPtr2( ByVal value As String ) As Boolean Public Class LibWrap ' Declares managed prototypes for unmanaged functions. Declare Sub TestCallBack Lib "..\LIB\PinvokeLib.dll" ( ByVal cb _ As FPtr, ByVal value As Integer ) Declare Sub TestCallBack2 Lib "..\LIB\PinvokeLib.dll" ( ByVal cb2 _ As FPtr2, ByVal value As String ) End Class 'LibWrap C# 复制代码 public delegate bool FPtr( int value ); public delegate bool FPtr2( String value ); public class LibWrap {// Declares managed prototypes for unmanaged functions. [ DllImport( "..\\LIB\\PinvokeLib.dll" )] public static extern void TestCallBack( FPtr cb, int value ); [ DllImport( "..\\LIB\\PinvokeLib.dll" )] public static extern void TestCallBack2( FPtr2 cb2, String value ); } 调用函数 Visual Basic 复制代码 Public Class App Public Shared Sub Main() Dim cb As FPtr cb = AddressOf App.DoSomething Dim cb2 As FPtr2 cb2 = AddressOf App.DoSomething2 LibWrap.TestCallBack( cb, 99 ) LibWrap.TestCallBack2( cb2, "abc" ) End Sub 'Main Public Shared Function DoSomething( ByVal value As Integer ) As Boolean Console.WriteLine( ControlChars.CrLf + "Callback called with _ param: {0}", value ) … End Function 'DoSomething Public Shared Function DoSomething2( ByVal value As String ) As Boolean Console.WriteLine( ControlChars.CrLf + "Callback called with _ param: {0}", value ) … End Function 'DoSomething2 End Class 'App C# 复制代码 public class App { public static void Main() { FPtr cb = new FPtr( App.DoSomething ); LibWrap.TestCallBack( cb, 99 ); FPtr2 cb2 = new FPtr2( App.DoSomething2 ); LibWrap.TestCallBack2( cb2, "abc" ); } public static bool DoSomething( int value ) { Console.WriteLine( "\nCallback called with param: {0}", value ); … } public static bool DoSomething2( String value ) { Console.WriteLine( "\nCallback called with param: {0}", value ); … } } 请参见 概念 其他封送处理示例 平台调用数据类型 在托管代码中创建原型 发送反馈意见,就此主题向 Microsoft 发送反馈意见。 |
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理 |
关注 hdt 倦怠 等级: | #4 得分:0回复于: 2012-12-08 11:06:53 不用把 委托转为 intptr,而是直接传委托 |
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理 |
关注 kndyc kndyc 等级: | #5 得分:0回复于: 2012-12-08 12:05:44 我是在C++的DLL中写了一个TestCallBack函数,但是在调用cb的时候抛出了异常,直接传委托也不行 |
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理 |
关注 zanfeng 1060151476 等级: | #6 得分:20回复于: 2012-12-08 13:23:14 可以的。 写了一个简单的例子 C# code ? | ||
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理 |
关注 zanfeng 1060151476 等级: | #7 得分:0回复于: 2012-12-08 13:24:12 C/C++ code ? ? C/C++ code ? | ||||||
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理 |
关注 kndyc kndyc 等级: | #8 得分:0回复于: 2012-12-08 13:38:18 我是这样做的,然后就抛出了异常。其实就是想要在C++里面调用C#的DoSomething函数 C/C++ code ? | ||
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理 |
关注 sp1234 以专业开发人员为伍 等级: 3 7 | #9 得分:10回复于: 2012-12-08 13:42:09 引用 8 楼 kndyc 的回复: 我是这样做的,然后就抛出了 你是怎样做的? 要注意到,它(也许不经意间)使用了 public static 修饰符。 |
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理 |
关注 kndyc kndyc 等级: | #10 得分:0回复于: 2012-12-08 14:03:28 原来没有加static,但是我用new给委托分配了空间,刚才加了public static修饰符还是一样的异常 |
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理 |
关注 zanfeng 1060151476 等级: | #11 得分:0回复于: 2012-12-08 19:46:50 引用 8 楼 kndyc 的回复: 我是这样做的,然后就抛出了异常。其实就是想要在C++里面调用C#的DoSomething函数 C/C++ code?1234void TestCallBack(void* pf, int value){ pf();} DoSomething是带有参数的。 而你的函数指针是没有参数的。不异常都不正常。 |
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理 |
关注 sp1234 以专业开发人员为伍 等级: 3 7 | #12 得分:0回复于: 2012-12-08 20:19:47 引用 10 楼 kndyc 的回复: 原来没有加static,但是我用new给委托分配了空间,刚才加了public static修饰符还是一样的异常 什么意思?mew? 动态分配内存的东西,你不怕垃圾回收吗? |
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理 |
关注 sp1234 以专业开发人员为伍 等级: 3 7 | #13 得分:0回复于: 2012-12-08 20:21:16 晕死!低级的系统是个死板的东西,你只能把纯粹静态方法作为参数。 |
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理 |
关注 kndyc kndyc 等级: | #14 得分:0回复于: 2012-12-08 20:37:53 引用 11 楼 zanfeng 的回复: 引用 8 楼 kndyc 的回复:我是这样做的,然后就抛出了异常。其实就是想要在C++里面调用C#的DoSomething函数 C/C++ code?1234void TestCallBack(void* pf, int value){ pf();} DoSomething是带有参数的。 而你的函数指针是没有参数的。不异常都不正常。 我声明的DoSomething原型就是不带参数的 |
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理 |
关注 kndyc kndyc 等级: | #15 得分:0回复于: 2012-12-08 20:40:28 引用 13 楼 sp1234 的回复: 晕死!低级的系统是个死板的东西,你只能把纯粹静态方法作为参数。 什么纯粹静态呢?把回调函数定义成public static还是一样异常。 |
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理 |
关注 zanfeng 1060151476 等级: | #16 得分:0回复于: 2012-12-08 20:50:04 C/C++ code ? C# code ? | ||||
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理 |
关注 kndyc kndyc 等级: | #17 得分:0回复于: 2012-12-08 22:22:50 引用 16 楼 zanfeng 的回复: C/C++ code?1234567891011121314// 此类是从 testlib.dll 导出的class TESTLIB_API Ctestlib {public: Ctestlib(void); // TODO: 在此添加您的方法。}; extern TESTLIB_API int ntestlib; TESTLIB_API int fntest…… 谢谢,确实可以输出了,但是我在C++当中一直不停的调用回调函数,怎样定义纯粹的静态方法,保证回调函数不被垃圾回收呢?我试了回调函数被调用几次以后就被垃圾回收了。 |
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理 |
关注 kndyc kndyc 等级: | #18 得分:0回复于: 2012-12-09 16:03:17 回调函数确实被垃圾回收了,因为定义的位置错了,改过来就好了。 |
相关文章推荐
- C++.NET编程体验
- C# 调用 C++
- C++ const总结
- 小玩文件3
- 哈夫曼算法(haffman)实现压缩和解压缩-C语言实现
- MFC多线程的创建
- Qt/C++ qss一些记录
- 第9周课后实践1-①
- C++关于指针----参考图
- 求最大公约数
- C++中cin、cin.get()、cin.getline()、getline()、gets()等函数的用法
- c语言中strtok的使用
- C++中map操作
- *leetcode #99 in cpp
- 「C语言」Windows+EclipseCDT下的C语言开发环境准备
- C++学习写在前面
- Eclipse运行C++问题Launch failed,Binary not found
- c++ 中__declspec 的用法
- Reconstruct Itinerary
- python调用c/c++