(C++/CLI) 如何在 C++ CLI 中获取从本机代码到托管代码的回调?
Posted
技术标签:
【中文标题】(C++/CLI) 如何在 C++ CLI 中获取从本机代码到托管代码的回调?【英文标题】:(C++/CLI) How to get callbacks from Native Code to Managed Code in C++ CLI? 【发布时间】:2021-12-03 17:10:57 【问题描述】:咆哮开始 在直接进入已经回答的乐队之前,请阅读这篇关于 SE 过时答案的论文https://ieeexplore.ieee.org/document/8669958
事情会在一段时间后发生变化,我担心计算机科学是 API 和接口变化非常非常快的领域中最多的领域之一。不用说,在将最新功能添加到平台/框架之后,上个月可能有效的解决方案可能不会。当许多主流事物甚至不存在时,我谦虚地请求您不要将这个问题标记为十年前的帖子已回答。如果您不知道最新的解决方案,请不要为此烦恼,并将问题留给可能的其他人。
对于计算机科学的社区代表来说,创新是日常事物,这是非常有毒的,新来者不友好和保守。 结束-RANT
我已经回答了这个问题,明天将被接受(SE 政策)。感谢您的关注。
很多时候你在非托管上下文中有函数指针,它们被某种事件调用,我们将看到如何使用***函数以及托管类的成员函数来实现它。
同样,请不要通过链接到十年前的帖子将其标记为已回答。
PS: 由于第三世界国家的互联网不稳定而进行了如此多的编辑,是的,咬我!
【问题讨论】:
这能回答你的问题吗? c++/cli pass (managed) delegate to unmanaged code 该答案已有 11 年历史,并且使用了漫长而复杂的方法,但可以以更简单的方式完成。 【参考方案1】:unmanaged.cpp
#pragma unmanaged
// Declare an unmanaged function type that takes one int arguments and callbacks
// our function after incrementing it by 1
// Note the use of __stdcall for compatibility with managed code
// if your unmanaged callback uses any other calling convention you can
// UnmanagedFunctionPointerAttribute (check msdn for more info) on your delegate
typedef int(__stdcall* ANSWERCB)(int);//Signature of native callback
int TakesCallback(ANSWERCB fp, int a)
if (fp)
return fp(a+1);//Native Callback
// This code will be executed when passed without fp
return 0;
#pragma managed
托管.cpp
using namespace System;
using namespace System::Runtime::InteropServices;
namespace Callbacks
// Following delegate is for unmanaged code and must match its signature
public delegate void MyNativeDelegate(int i);
// This delegate is for managed/derived code and ideally should have only managed parameters
public delegate void MyManagedDelegate(int i);
public ref class TestCallback // Our demo Managed class
private:
GCHandle gch;// kept reference so that it can be freed once we are done with it
void NativeCallbackListener(int i);//unmanaged code will call this function
public:
void TriggerCallback(int i); // Its here for demo purposes, usually unmanaged code will call automatically
event MyManagedDelegate^ SomethingHappened;//plain old event
~TestCallback();//free gch in destructor as its managed.
;
;
void Callbacks::TestCallback::NativeCallbackListener(int i)
// Callback from Native code,
// If you need to transform your arguments do it here, like transforming void* to somekind of native structure.
// and then pass SomethingHappened::raise with Managed Class/Struct
return SomethingHappened::raise(i); // similar to SomethingHappened.Invoke() in c#
void Callbacks::TestCallback::TriggerCallback(int i)
MyNativeDelegate^ fp = gcnew MyNativeDelegate(this, &TestCallback::NativeCallbackListener);
// use this if your nativecallback function is not a member function MyNativeDelegate^ fp = gcnew MyNativeDelegate(&NativeCallbackListener);
gch = GCHandle::Alloc(fp);
IntPtr ip = Marshal::GetFunctionPointerForDelegate(fp);
ANSWERCB cb = static_cast<ANSWERCB>(ip.ToPointer());// (ANSWERCB)ip.ToPointer(); works aswell
// Simulating native call, it should callback to our function ptr NativeCallbackListener with 2+1;
// Ideally Native code keeps function pointer and calls back without pointer being provided every time.
// Most likely with a dedicated function for that.
TakesCallback(cb, i);
void Callbacks::TestCallback::~TestCallBack()
gch.Free();//Free GCHandle so GC can collect
implementation.cpp
using namespace System;
void OnSomethingHappened(int i);
int main(array<System::String^>^ args)
auto cb = gcnew Callbacks::TestCallback();
cb->SomethingHappened += gcnew Callbacks::MyManagedDelegate(&OnSomethingHappened);
cb->TriggerCallback(1);
return 0;
void OnSomethingHappened(int i)
Console::WriteLine("Got call back with " + i);
【讨论】:
您能否更详细地指出我们这里发生了什么?你的代码是做什么的? 它是一个示例,模仿现实世界的应用程序互操作。以上是关于(C++/CLI) 如何在 C++ CLI 中获取从本机代码到托管代码的回调?的主要内容,如果未能解决你的问题,请参考以下文章
C++/CLI + C++ Native 会提高性能吗? [关闭]
DeviceIoControl 在 C++ 和 C# 中工作,但在 C++/CLI 中调用时返回 ERROR_INVALID_FUNCTION