C ++ / CLI编组.NET代表天然委托(C++/CLI marshaling .NET del

2019-10-30 04:22发布

我试图通过一个委托与被调用管理参数,为本地代码。 我下面的代码运行正常,但串组输出是垃圾。

本机类

#pragma once
typedef void (* SegmentCreatedDelegate)(char** arg);
public class SampleClass
{
public:
    SampleClass(void);
    ~SampleClass(void);
    void DoWork(SegmentCreatedDelegate callback);
};

SampleClass::SampleClass(void)
{
}

SampleClass::~SampleClass(void)
{

}

void SampleClass::DoWork(SegmentCreatedDelegate callback)
{
    for(int x = 0; x< 10; x++)
    {
        char* myStr2 = "newsegment!";
        callback(&myStr2);
    }
}

托管班

#pragma once
public ref class SampleClassNet
{
public:
    delegate void SegmentCreatedDelegateNet(System::String^ arg);
    SampleClassNet(void);
    void DoWork(SegmentCreatedDelegateNet^ segmentCreatedCallback);
};

SampleClassNet::SampleClassNet(void)
{
}

void SampleClassNet::DoWork(SegmentCreatedDelegateNet^ segmentCreatedCallback)
{
    SampleClass* nativeClass = new SampleClass();
    System::IntPtr pointer = System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(segmentCreatedCallback);
    nativeClass->DoWork((SegmentCreatedDelegate)(void*)pointer);
    System::GC::KeepAlive(segmentCreatedCallback);
}

此代码运行正常与后续的C#。

var sampleClass = new SampleClassNet();
sampleClass.DoWork((Console.WriteLine));

除非我得到以下输出,而不是预期的10项“newsegment!”。

(ÇÆX
(ÇÆX☺
(ÇÆX☻
(ÇÆX♥
(ÇÆX♦
(ÇÆX♣
(ÇÆX♠
(ÇÆX
(ÇÆX
(ÇÆX

不正是“newsegment!”,但我不知道为什么封送不工作。 也许我需要,我需要某种“的MarshalAs”属性,使得系统::字符串都知道,我有8位字符?

Answer 1:

正如在评论中提到的,你应该在转换char**String^ 。 (顺便说一下,为什么通过char** ,不char*String有一个建筑工采取char* ,这可能会简化了很多东西。)

我没有试过以下,但你可能会试一试:

public ref class SampleClassNet {
private:
    delegate void SegmentCreatedDelegateNative(char** str);
    SegmentCreatedDelegateNet^ managedCallback;
    SegmentCreatedDelegateNative^ nativeCallback;
    void printString(char** string);
public:
    delegate void SegmentCreatedDelegateNet(System::String^ arg);
    SampleClassNet();
    void DoWork(SegmentCreatedDelegateNet^ segmentCreatedCallback);
};

SampleClassNet::SampleClassNet() {
    nativeCallback = printString;
}

void SampleClassNet::DoWork(SegmentCreatedDelegateNet^ segmentCreatedCallback) {
    SampleClass* nativeClass = new SampleClass();
    managedCallback = segmentCreatedCallback;
    System::IntPtr pointer = System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(nativeCallback);
    nativeClass->DoWork((SegmentCreatedDelegate)(void*)pointer);
}

void SampleClassNet::printString(char** string) {
    if (this->managedCallback != nullptr) {
        String^ str = gcnew String(*string);
        managedCallback(str);
    }
}

其基本思想是用另一种代表, SegmentCreatedDelegateNative ,交给本机类,并呼吁从与包装相关的功能的实际管理委托。



文章来源: C++/CLI marshaling .NET delegate to native delegate