gpt4 book ai didi

c++-cli - 使用 native 函数指针来监听托管事件/编码问题

转载 作者:行者123 更新时间:2023-12-04 02:30:38 25 4
gpt4 key购买 nike

我正在编写一个混合模式 C++/CLI 程序集桥,以便能够从旧的 C++ 应用程序调用我的 .NET 类库。

在我的 .NET 库中的一个类中,只要需要显示某些消息(到控制台或取决于调用应用程序的任何内容),就可以将其附加到事件。

class NetApi
{
public event EventHandler<MessageEventArgs> MessageReported;
}

为了从 native C++ 应用程序调用它,我定义了以下指针/委托(delegate)桥:
typedef void(*MessageHandler)(const char* msg);
delegate void ManagedMessageHandler([MarshalAs(UnmanagedType::LPStr)] String^ msg);

省略胶水以连接所有内容(附加到 MessageReported ,从 sender 中删除 EventHandler 等...),这是我从 native 函数指针创建托管委托(delegate)的方法:
class NetApiBridge
{
public:
void SetMessageHandler(MessageHandler handler)
{
wrappedListener = (ManagedMessageHandler^)Marshal::GetDelegateForFunctionPointer((IntPtr)handler, ManagedMessageHandler::typeid);
}

private:
msclr::auto_gcroot<NetApi^ > wrappedApi;
msclr::auto_gcroot<ManagedMessageHandler^ > wrappedListener;

// In another helper ref class in fact, but here pseudo code to simplify
void onMessageReported(Object^ sender, MessageEventArgs^ e)
{
if (!wrappedListener) { return; }

wrappedListenter(e->Message); // Send message to native function pointer
}
}

在创建虚拟 C++ 测试代码时,我几乎就在那里:
void messageHandler(const char* s)
{
cout << s;
}
void main()
{
NetApiBridge api = new NetApiBridge();
api->SetMessageHandler(&messageHandler);

api->Measure();
delete api;
}

一切正常,事件报告正确,除了....除了我收到 PInvokeStackImbalance离开 native 处理程序时来自托管调试助手,我显然不知道为什么?

编码有什么问题 const char*UnmanagedType::LPStr这里有 GetDelegateForFunctionPointer ?

注意:C++ 桥接器在 x86 中编译,如果在这里知道很重要的话。

最佳答案

typedef void(*MessageHandler)(const char* msg);
delegate void ManagedMessageHandler([MarshalAs(UnmanagedType::LPStr)] String^ msg);

您的委托(delegate)声明与 32 位代码中的函数指针声明不兼容。 native 代码中的默认调用约定几乎总是 __cdecl .代表的默认值为 __stdcall .一个有点古怪的选择,但受到启发,因为互操作被认为对进行操作系统调用很有用,Windows 和 COM 使用 __stdcall。

现在的不匹配导致委托(delegate) stub 将参数从堆栈中弹出。 native 代码也是如此,因此堆栈不平衡了 4 个字节。 MDA 可以帮助您诊断这种常见的事故。

您必须提供帮助并让他们同意。使用委托(delegate)声明:
   using namespace System::Runtime::InteropServices;
...
[UnmanagedFunctionPointer(CallingConvention::Cdecl)]
delegate void ManagedMessageHandler(String^ msg);

或者函数指针声明:
   typedef void (__stdcall * MessageHandler)(const char* msg);

关于c++-cli - 使用 native 函数指针来监听托管事件/编码问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37486458/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com