0

我正在通过 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.) 为什么这段代码不起作用?尽管它很丑陋,但在我看来它应该可以工作,因为我认为指针正在正确传递......

谢谢你的帮助!

4

0 回答 0