Skip to main content
 首页 » 编程设计

delegates之c++/cli 将(托管)委托(delegate)传递给非托管代码

2024年11月01日14zdz8207

如何将函数指针从托管 C++ (C++/CLI) 传递给非托管方法?我读了几篇文章,例如 this one from MSDN ,但它描述了两个不同的程序集,而我只想要一个。

这是我的代码:

1)标题(MyInterop.ManagedCppLib.h):

#pragma once 
 
using namespace System; 
 
namespace MyInterop { namespace ManagedCppLib { 
 
    public ref class MyManagedClass 
    { 
    public: 
        void DoSomething(); 
    }; 
}} 

2) CPP 代码 (MyInterop.ManagedCppLib.cpp)
#include "stdafx.h" 
#include "MyInterop.ManagedCppLib.h" 
 
#pragma unmanaged 
void UnmanagedMethod(int a, int b, void (*sum)(const int)) 
{ 
    int result = a + b; 
    sum(result); 
} 
 
#pragma managed 
void MyInterop::ManagedCppLib::MyManagedClass::DoSomething() 
{ 
    System::Console::WriteLine("hello from managed C++"); 
    UnmanagedMethod(3, 7, /* ANY IDEA??? */); 
} 

我尝试创建托管委托(delegate),然后尝试使用 Marshal::GetFunctionPointerForDelegate方法,但我无法编译。

请您参考如下方法:

是的,你想要 Marshal::GetFunctionPointerForDelegate()。您的代码片段缺少您要调用的托管函数,我只是编造了一个。您还必须声明托管委托(delegate)类型并创建它的实例,然后才能获得函数指针。这很好用:

#include "stdafx.h" 
 
using namespace System; 
using namespace System::Runtime::InteropServices; 
 
#pragma managed(push, off) 
typedef void (* UnmanagedSummer)(int arg); 
 
void UnmanagedMethod(int a, int b, UnmanagedSummer sum) 
{ 
    int result = a + b; 
    sum(result); 
} 
#pragma managed(pop) 
 
ref class Test { 
    delegate void ManagedSummer(int arg); 
public: 
    static void Run() { 
        Test^ t = gcnew Test(); 
        ManagedSummer^ managed = gcnew ManagedSummer(t, &Sum); 
        IntPtr stubPointer = Marshal::GetFunctionPointerForDelegate(managed); 
        UnmanagedSummer functionPointer = static_cast<UnmanagedSummer>(stubPointer.ToPointer()); 
        UnmanagedMethod(1, 2, functionPointer); 
        GC::KeepAlive(managed);    // Important: ensure stub can't be collected while native code is running 
        System::Diagnostics::Debug::Assert(t->summed == 3); 
    } 
    void Sum(int arg) { 
        summed += arg; 
    } 
    int summed; 
}; 
 
int main(array<System::String ^> ^args) 
{ 
    Test::Run(); 
    return 0; 
}