从包装了本机C ++类的CLI类中调用C#委托

时间:2019-06-13 12:35:44

标签: c# .net native

我有一个C ++类的CLI包装器。 C ++类具有传递的回调 一个char *数组以及该数组的长度。

void (CPP_CALLBACK*)(char* data, unsigned int dataLength)

在C#领域中,我有此回调

  private delegate void AppPacketReceivedDelegate(byte[] data);

我的CLI包装器收到CPP_CALLBACK回调,然后必须以某种方式调用C#委托。

有关如何执行此操作的任何想法?我尝试过

System::Action<cli::array<char>^>

但我不确定如何使委托与该操作匹配。

更新:

我将委托转换为函数指针,然后可以使用以下语法从CLI调用函数指针:

  typedef void(__stdcall * WRAPPER_APP_PACKET_CALLBACK) (cli::array<unsigned char>^);

但是,当我这样称呼时,数组的大小始终为1!

2 个答案:

答案 0 :(得分:1)

这是一个简单的示例,虽然与您的情况不完全匹配,但是可以快速进行调整。

CppClass.h

namespace MyCppNamespace
{
    typedef void (__stdcall *callback_function)(int, const char*);

    class CppClass
    {
    private:
        callback_function _callbackFunc;

    public:
        void DoSomething(callback_function callbackFunc);
    }
}

DotNetClass.cs

namespace MyManagedNamespace
{
    public delegate void ManagedCallback(int size, string message);
}

CliWrapperClass.h

#include "CppClass.h"

using namespace MyManagedNamespace;

namespace MyCliNamespace
{
    public ref class CliWrapperClass
    {
    private:
        CppClass *_cppClass;

    public:
        void DoSomething(ManagedCallback ^ callback);
    }
}

CliWrapperClass.cpp

#include "CliWrapperClass.h"

namespace MyCliNamespace
{
    void CliWrapperClass::DoSomething(ManagedCallback ^ callback)
    {        
        System::IntPtr callbackPtr = System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(callback);

        _cppClass->DoSomething(static_cast<callback_function>(callbackPtr.ToPointer())); 
    }
}

在.Net类中,您可以创建CliWrapperClass的实例并通过以下方式调用其DoSomething(...)函数:

namespace MyManagedNamespace
{
    public class ManagedClass
    {
        private ManagedCallback _callback = MyCallback;

        private void MyCallback(int size, string message)
        {
            // Do what you want ...
        }

        public void MyFunction()
        {
            CliWrapperClass wrapper = new CliWrapperClass();
            wrapper.DoSomething(_callback);
        }
    }
}

答案 1 :(得分:0)

最后,我将C#类和相应的委托标记为unsafe,然后 然后我可以从C ++调用委托并传递C样式数组。在C#端,我创建了一个托管数组,并使用Marshal.Copy

复制了字节