我正在通过 C# 互操作利用 C++ 库,它有一个简单的 API 在后台线程中执行一些任务。问题是执行后台任务的 C++ 函数采用一个空指针,然后在执行后台任务时“填充”该空指针。此外,线程是在 C# 端完成的,所以我不得不使用“ParameterizedThreadStart”委托类型,它只接受一个对象作为参数。然后我需要从我的 C# 代码中访问该对象。希望以下片段可以说明我的意思。
C++:
extern "C" void __declspec(dllexport) performLongTask(MyClass** myObject)
{
myObject = new MyClass;
// Time-consuming operation...
}
C#:
[DllImport("myDllName")]
public static extern void performLongTask(ref IntPtr myObject);
// Ugly, but necessary for ParameterizedThreadStart delegate?
unsafe class PtrWrapper
{
public IntPtr Pointer = new IntPtr();
}
public static unsafe performLongTask_paramThreadStartWrapper(object arg)
{
PtrWrapper ptrWrapper = (PtrWrapper)arg;
performLongTask(ref ptrWrapper.Pointer);
}
public static unsafe void DoInteropStuff()
{
PtrWrapper ptrWrapper = new PtrWrapper();
Thread bgThread = new Thread(new ParameterizedThreadStart(performLongTask_paramThreadStartWrapper));
bgThread.Start(ptrWrapper);
// Wait a little while, let background thread processing go....
// Use pointer to retrieve some stuff from other unmanaged code
if(ptrWrapper.Pointer != IntPtr.Zero)
object currentData = getData(ptrWrapper.Pointer);
}
这样做的结果是我在托管端创建的 IntPtr 永远不会改变,尽管事实上非托管代码似乎执行得很好(调试打印语句显示事情按预期进行,并且指针肯定已设置为非托管方)。
我知道这不是最漂亮的代码,并且可能有几种方法可以让整个事情变得更干净。我对几件事感兴趣:
1.) 如何以最好的方式使用 C++ 库来实现这一点(不修改非托管代码)。
2.) 为什么这段代码不起作用?尽管它很丑陋,但在我看来它应该可以工作,因为我认为指针正在正确传递......
谢谢你的帮助!