我正在尝试将托管参数的委托传递给要调用的本机代码。我的代码运行正常,但字符串输出是垃圾。
#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位字符?
答案 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
,交给本机类,并从与包装器关联的函数中调用实际的托管委托。