C ++ / CLI封送.NET委托给本机委托

时间:2014-01-10 21:36:31

标签: delegates c++-cli marshalling

我正在尝试将托管参数的委托传递给要调用的本机代码。我的代码运行正常,但字符串输出是垃圾。

原生班级

标题

#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”属性,以便System :: String知道我有8位字符?

1 个答案:

答案 0 :(得分:0)

正如评论中所述,您应该将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,交给本机类,并从与包装器关联的函数中调用实际的托管委托。