C#调用C++/CLI本地代码的回调函数

yeaphi 2012-09-24 11:16:27
c++ dll
CClientGlobal.h
class __declspec(dllexport) CClientGlobal
{
public:
typedef int (*pMsgHandleResponseFunc)(CMsg*,vector<CMsg*>&);
typedef int (*pRequestTimeOutFunc)(int _CMDID);
void Set_Response(pMsgHandleResponseFunc fp){};
void Set_Timeout(pRequestTimeOutFunc fp){};
void Set_Response(void* p){};
void Set_Timeout(void* p){};
}

c++/cli wrapper 库
native head
CClientGlobal.h
class __declspec(dllexport) CClientGlobal
{
public:
typedef int (*pMsgHandleResponseFunc)(CMsg*,vector<CMsg*>&);
typedef int (*pRequestTimeOutFunc)(int _CMDID);
void Set_Response(pMsgHandleResponseFunc fp){};
void Set_Timeout(pRequestTimeOutFunc fp){};
void Set_Response(void* p){};
void Set_Timeout(void* p){};

}

wrapper head
public ref class CClientGlobalWrapper
{
CClientGlobal* NativeClientGlobal;
public:
CClientGlobalWrapper(void);
~CClientGlobalWrapper();
public: //消息发送

typedef int (*pMsgHandleResponseFunc)(CMsg*,vector<CMsg*>&);
typedef int (*pRequestTimeOutFunc)(int _CMDID);


void Set_Response(void* fp);
void Set_Response(pMsgHandleResponseFunc fp);


void Set_Timeout(void* fp);
void Set_Timeout(pRequestTimeOutFunc fp);
};



我没有使用显示声明dll函数的方式,而是在C#中添加C++/cli封装的dll,
CClientGlobalWrapper cgw = new CClientGlobalWrapper();
pMsgHandleResponseFunc msgh = new pMsgHandleResponseFunc(MsgHandle);
cgw.Set_Response() 方法只能看到void*的参数,而看不到函数指针的参数


有没有兄弟有这方面经验的,请帮忙解决一下
...全文
355 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
yeaphi 2012-09-24
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]
引用 2 楼 的回复:

引用 1 楼 的回复:

显然这个C++/CLR(不是cli)……

“C++/CLI(CLI: Common Language Infrastructure)在计算机语言中是一门由微软设计,用来代替C++托管扩展(下文使用MC++指代)的语言。” —— Wikipedia

To LZ:
CClientGlobalWrapper 公开的 Set_Res……
[/Quote]


可以考虑一下,我本意是使用CLI封装后就可以直接使用了,节省开发成本
qldsrx 2012-09-24
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]

引用 1 楼 的回复:

显然这个C++/CLR(不是cli)……

“C++/CLI(CLI: Common Language Infrastructure)在计算机语言中是一门由微软设计,用来代替C++托管扩展(下文使用MC++指代)的语言。” —— Wikipedia

To LZ:
CClientGlobalWrapper 公开的 Set_Response/Set_Tim……
[/Quote]
The CLR is Microsoft's implementation of the CLI standard.
看来说CLI也可以,不过我还是习惯微软的那个CLR叫法了,毕竟这东西目前只有微软提供。
qldsrx 2012-09-24
  • 打赏
  • 举报
回复
参数也重新定义啊,当C++接收到C#传递过来的重定义参数,你手动遍历重定义参数里面的属性,给C++里面的那个CMsg结构体赋值,然后将返回的那个vector<CMsg*>引用手动转换为C#可识别的List<T>形式(vector等价于List)
yeaphi 2012-09-24
  • 打赏
  • 举报
回复
delegate int MsgHandleResponseFunc(CMsg*,vector<CMsg*>&);
delegate int RequestTimeOutFunc(int _CMDID);

我在clr里改成了上述两句后,确实可以调用,但还是碰到了新的问题,在于回调函数的参数如何在C#中做对应转换,还是两位帮忙,我确实是第一次,没啥经验,谢谢了。
lq6711923 2012-09-24
  • 打赏
  • 举报
回复
楼上解释的不错
iyomumx 2012-09-24
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

显然这个C++/CLR(不是cli)……
[/Quote]
“C++/CLI(CLI: Common Language Infrastructure)在计算机语言中是一门由微软设计,用来代替C++托管扩展(下文使用MC++指代)的语言。” —— Wikipedia

To LZ:
CClientGlobalWrapper 公开的 Set_Response/Set_Timeout不应该再使用非托管的函数指针形式而是使用托管的委托形式,再在方法体中添加互操作代码,比如 Marshal.GetFunctionPointerForDelegate 函数的调用。
注意vector<CMsg*>在托管代码中没有等效的封装,需要自行封装/拆封。
qldsrx 2012-09-24
  • 打赏
  • 举报
回复
显然这个C++/CLR(不是cli)的封装有错误,既然你要提供C#调用,那么输入输出参数就必须是C#中可以识别的类型,但是你这里却用了非托管类型作为参数,那么虽然能够看到函数,但是调用不能。C++/CLR是可以同时识别非托管和托管类型的,且转换方便,那么你所做的事情就是在C++里面定义一个托管类型的pMsgHandleResponseFunc和pRequestTimeOutFunc,然后自己做转换。

111,041

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧