Delegates c++/cli将(托管)委托传递给非托管代码 如何将函数指针从托管C++(C++ +CLI)传递到非托管方法?我读了一些文章,比如,但它描述了两个不同的程序集,而我只想要一个

Delegates c++/cli将(托管)委托传递给非托管代码 如何将函数指针从托管C++(C++ +CLI)传递到非托管方法?我读了一些文章,比如,但它描述了两个不同的程序集,而我只想要一个,delegates,c++-cli,interop,function-pointers,Delegates,C++ Cli,Interop,Function Pointers,这是我的密码: 1) 标题(MyInterop.ManagedCppLib.h): 2) CPP代码(MyInterop.ManagedCppLib.CPP) 我尝试创建托管委托,然后尝试使用封送::GetFunctionPointerForDelegate方法,但无法编译。是的,您需要封送::GetFunctionPointerForDelegate()。您的代码段缺少您想要调用的托管函数,我刚刚编了一个。在获取函数指针之前,还必须声明托管委托类型并创建其实例。这很有效: #include "

这是我的密码:

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

2) CPP代码(MyInterop.ManagedCppLib.CPP)


我尝试创建托管委托,然后尝试使用
封送::GetFunctionPointerForDelegate
方法,但无法编译。

是的,您需要封送::GetFunctionPointerForDelegate()。您的代码段缺少您想要调用的托管函数,我刚刚编了一个。在获取函数指针之前,还必须声明托管委托类型并创建其实例。这很有效:

#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;
}
#包括“stdafx.h”
使用名称空间系统;
使用名称空间System::Runtime::InteropServices;
#pragma管理(推、关)
typedef void(*非托管摘要)(int arg);
void非托管方法(int a、int b、非托管求和)
{
int结果=a+b;
总和(结果);
}
#布拉格语管理(pop)
参考等级测试{
委托void ManagedSummer(int arg);
公众:
静态无效运行(){
Test^t=gcnew Test();
ManagedSummer^managed=gcnewmanagedSummer(t,&Sum);
IntPtr stubPointer=Marshal::GetFunctionPointerForDelegate(托管);
UnmanagedSummer functionPointer=static_cast(stubPointer.ToPointer());
非托管方法(1,2,functionPointer);
GC::KeepAlive(托管);//重要提示:确保在本机代码运行时无法收集存根
系统::诊断::调试::断言(t->summated==3);
}
无效和(整型参数){
总和+=arg;
}
整数和;
};
int main(数组^args)
{
Test::Run();
返回0;
}

下面是基于我在C++/CLI中实现.NETWrap C++ C++地图绘制库的经验的另一种方法。这是经过测试和运行的代码

C++ API有一个异步查找函数,它调用回调:

TResult CartoType::CFramework::FindAsync(FindAsyncCallBack aCallBack,const TFindParam& aFindParam,bool aOverride = false);
回调函数是这种类型的函数:

using FindAsyncCallBack = std::function<void(std::unique_ptr<CMapObjectArray> aMapObjectArray)>;
因此,.NET函数的签名为:

Result FindAsync(FindAsyncDelegate^ aDelegate,FindParam^ aFindParam,bool aOverride);

主要解决的问题是如何调用本机C++函数,并提供一个本地调用函数,然后调用由.NET函数调用方传递的委托。关联的任务是使委托和本机回调函数对象保持活动状态,直到异步函数的线程完成其工作。这是怎么做到的

我定义了一个C++ + CLI委托类型,它与C++回调函数类型相同,并且一个类将调用方传递的委托保存到(.FasaSycCeDePATE类型)的.NET函数,以及要传递给C++(类型NATEVEAsIN)的委托:< /P> 创建FindAsyncHandler对象并在其中存储本机处理程序对象;将其保留在这里意味着我们只有一个对象保持活动状态,即FindAsyncHandler。下面的发言:

IntPtr p = Marshal::GetFunctionPointerForDelegate(h->m_native_handler);
FIND_ASYNC_CALLBACK f = static_cast<FIND_ASYNC_CALLBACK>(p.ToPointer());
然后,为了确保各种回调函数保持活动状态,FindAsyncHandler被添加到主框架对象拥有的列表中:

m_find_async_helper_list->Add(h);

当任务完成并调用FindAsyncHelper::Handler时,它将从列表中删除。

请发布您使用GetFunctionPointerForDelegate的代码好吗?这个额外的强制转换是“缺少的链接”:-)谢谢!
Result FindAsync(FindAsyncDelegate^ aDelegate,FindParam^ aFindParam,bool aOverride);
delegate void NativeAsyncHandler(std::unique_ptr<CMapObjectArray> aMapObjectArray);

ref class FindAsyncHelper
    {
    public:
    FindAsyncHelper(Framework^ aFramework,FindAsyncDelegate^ aDelegate):
        m_framework(aFramework),
        m_delegate(aDelegate)
        {
        }

    void Handler(std::unique_ptr<CMapObjectArray> aMapObjectArray)
        {
        MapObjectList^ o = gcnew MapObjectList;
        SetMapObjectList(m_framework,o,*aMapObjectArray);
        m_delegate(o);

        // Remove this object from the list held by the framework so that it can be deleted.
        m_framework->m_find_async_helper_list->Remove(this);
        }

    Framework^ m_framework;
    FindAsyncDelegate^ m_delegate;
    NativeAsyncHandler^ m_native_handler;
    };
typedef void(*FIND_ASYNC_CALLBACK)(std::unique_ptr<CMapObjectArray> aMapObjectArray);

Result Framework::FindAsync(FindAsyncDelegate^ aDelegate,FindParam^ aFindParam,bool aOverride)
    {
    if (aDelegate == nullptr || aFindParam == nullptr)
        return Result::ErrorInvalidArgument;
    TFindParam param;
    SetFindParam(param,aFindParam);

    FindAsyncHelper^ h = gcnew FindAsyncHelper(this,aDelegate);
    h->m_native_handler = gcnew NativeAsyncHandler(h,&FindAsyncHelper::Handler);

    IntPtr p = Marshal::GetFunctionPointerForDelegate(h->m_native_handler);
    FIND_ASYNC_CALLBACK f = static_cast<FIND_ASYNC_CALLBACK>(p.ToPointer());
    TResult error = m_framework->FindAsync(f,param,aOverride);

    // Keep h alive by adding it to a list.
    m_find_async_helper_list->Add(h);

    return (Result)(int)error;
    }
FindAsyncHelper^ h = gcnew FindAsyncHelper(this,aDelegate);
h->m_native_handler = gcnew NativeAsyncHandler(h,&FindAsyncHelper::Handler);
IntPtr p = Marshal::GetFunctionPointerForDelegate(h->m_native_handler);
FIND_ASYNC_CALLBACK f = static_cast<FIND_ASYNC_CALLBACK>(p.ToPointer());
TResult error = m_framework->FindAsync(f,param,aOverride);
m_find_async_helper_list->Add(h);