我试图通过PInvoke将回调从托管的C#程序整理到本地C ++ DLL。这些回调可能会在一个单独的线程上长时间延迟后被调用。我当前的设计发现,如果在本机层立即调用正确的数据,则可以正确调用回调,但是如果在单独的线程上延迟调用,则失败。这是设置的简单示例:
C#接口
public class Example
{
private delegate void NativeLoginCallback(IntPtr bytes);
[DllImport ("NativeExample")]
private static extern void Example_loginAsync(NativeLoginCallback callback);
private delegate void LoginCallback(string data);
public void LoginAsync(LoginCallback callback)
{
NativeLoginCallback nativeCallback = (IntPtr bytes) =>
{
string data = MarshalUtility.Deserialize<string>(bytes);
try
{
callback(data);
}
catch (Exception ex)
{
Debug.Log(ex);
}
}
Example_loginAsync(nativeCallback);
}
}
C接口
extern "C" __declspec(dllimport) void Example_loginAsync(void* callback)
{
typedef void(*CSharpLoginCallbackType)(void* data);
CSharpLoginCallbackType csharpCallback = (CSharpLoginCallbackType) callback;
auto cppLoginCallback = [csharpCallback](std::string data)
{
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
unsigned char* dataBytes;
MarshalUtility::Serialize(data, dataBytes);
csharpCallback(dataBytes);
};
std::string testData = "This one is called immediately on same thread.";
unsigned char* testDataBytes;
MarshalUtility::Serialize(testData, testDataBytes);
csharpCallback(testDataBytes);
std::thread t(cppLoginCallback, "This one is called after 5 seconds on seperate thread.");
t.detach();
}
C#呼叫者
public class ExampleIntegrator
{
Example example = new Example();
public void Test()
{
example.Login((string data) =>
{
Debug.Log(data);
};
}
};
我看到的输出是:
This one is called immediately on same thread.
NullReferenceException
我期望的输出是:
This one is called immediately on same thread.
This one is called after 5 seconds on seperate thread.
经检查,我发现在NativeLoginCallback范围内数据是正确的,即在行string data = MarshalUtility.Deserialize<string>(bytes);
之后,调试器正确显示在单独的线程上5秒钟后调用了该代码。,但是发现回调是NullReference。如何确保回调不会为空?