C++ cli 使用本机函数指针侦听托管事件/封送处理问题 我正在编写一个混合模式的C++/CLI汇编桥,以便能够从旧的C++应用程序调用到.Net类库。 class NetApi { public event EventHandler<MessageEventArgs> MessageReported; }

C++ cli 使用本机函数指针侦听托管事件/封送处理问题 我正在编写一个混合模式的C++/CLI汇编桥,以便能够从旧的C++应用程序调用到.Net类库。 class NetApi { public event EventHandler<MessageEventArgs> MessageReported; },c++-cli,function-pointers,marshalling,C++ Cli,Function Pointers,Marshalling,在.NET库中的我的一个类中,只要需要显示某些消息,就可以附加到事件(到控制台或任何依赖于调用应用程序的对象) 省略连接所有内容的胶水(附加到MessageReported,从EventHandler中删除sender,等等),下面是我如何从本机函数指针创建托管委托: class NetApiBridge { public: void SetMessageHandler(MessageHandler handler) { wrappedList

在.NET库中的我的一个类中,只要需要显示某些消息,就可以附加到事件(到控制台或任何依赖于调用应用程序的对象)

省略连接所有内容的胶水(附加到
MessageReported
,从
EventHandler
中删除
sender
,等等),下面是我如何从本机函数指针创建托管委托:

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
        }
}
classnetapibridge
{
公众:
void SetMessageHandler(MessageHandler处理程序)
{
wrappedListener=(ManagedMessageHandler^)封送::GetDelegateForFunctionPointer((IntPtr)处理程序,ManagedMessageHandler::typeid);
}          
私人:
msclr::autogcrootwrappedapi;
msclr::autogcrootwrappedListener;
//事实上,在另一个helper ref类中,这里是简化的伪代码
MessageReported无效(对象^sender,MessageEventArgs ^e)
{
如果(!wrappedListener){return;}
WrappedListener(e->Message);//将消息发送到本机函数指针
}
}
当创建虚构的C++测试代码:

时,我几乎在那里
void messageHandler(const char* s)
{
    cout << s; 
}
void main()
{
   NetApiBridge api = new NetApiBridge();
   api->SetMessageHandler(&messageHandler);

   api->Measure();
   delete api;
}
void消息处理程序(const char*s)
{
cout SetMessageHandler(&messageHandler);
api->Measure();
删除api;
}
一切正常,事件报告正确,除了。。。。除了我在离开本机处理程序时从托管调试助手处收到
pinvokestack
,我显然不知道为什么

使用
GetDelegateForFunctionPointer
const char*
封送为
UnmanagedType::LPStr
有什么问题

Nb:C++桥是在x86中编译的,如果这里知道的很重要。p>

typedef void(*MessageHandler)(const char* msg);
delegate void ManagedMessageHandler([MarshalAs(UnmanagedType::LPStr)] String^ msg);
您的委托声明与32位代码中的函数指针声明不兼容。本机代码中的默认调用约定几乎总是
\uu cdecl
。代理的默认值为
\u stdcall
。这是一个有点古怪的选择,但受到启发,因为互操作被认为对操作系统调用很有用,Windows和COM使用stdcall

现在的不匹配会导致委托存根从堆栈中弹出参数。本机代码也是如此,因此堆栈不平衡4字节。MDA将帮助您诊断这一常见的灾难

你必须帮助他们,让他们同意。使用委托声明:

   using namespace System::Runtime::InteropServices;
   ...
   [UnmanagedFunctionPointer(CallingConvention::Cdecl)]
   delegate void ManagedMessageHandler(String^ msg);
   typedef void (__stdcall * MessageHandler)(const char* msg);
或函数指针声明:

   using namespace System::Runtime::InteropServices;
   ...
   [UnmanagedFunctionPointer(CallingConvention::Cdecl)]
   delegate void ManagedMessageHandler(String^ msg);
   typedef void (__stdcall * MessageHandler)(const char* msg);

你是我今天的英雄!非常感谢:)我会回复你的赞美,这是我一周来读到的最好的问题。做得很好,你很容易帮助你。