C++/CLI 方法调用本地方法修改 int - 需要 pin_ptr?

C++/CLI method calls native method to modify int - need pin_ptr?

我有一个 C++/CLI 方法,ManagedMethod,其中一个输出参数将由本机方法修改:

// file: test.cpp

#pragma unmanaged
void NativeMethod(int& n)
{
   n = 123;
}
#pragma managed

void ManagedMethod([System::Runtime::InteropServices::Out] int% n)
{
   pin_ptr<int> pinned = &n;
   NativeMethod(*pinned);
}

void main()
{
   int n = 0;
   ManagedMethod(n);
   // n is now modified
}

一旦 ManagedMethod returns,n 的值已按我的预期进行了修改。到目前为止,我能够编译它的唯一方法是在 ManagedMethod 中使用 pin_ptr,那么固定实际上是 correct/only 的方法吗?或者是否有更优雅的方式将 n 传递给 NativeMethod

是的,这是正确的做法。在 CLR 内部进行了高度优化,该变量获得了 [pinned] 属性,因此 CLR 知道它存储了一个指向不应移动的对象的内部指针。与 GCHandle::Alloc() 不同,pin_ptr<> 可以在不创建另一个句柄的情况下完成。在table中报告说编译方法时会产生抖动,GC使用table知道在哪里寻找对象根。

只有当垃圾收集发生在 NativeMethod() 运行 的同一时间时,这才是重要的。在实践中不会经常发生,您必须在程序中使用线程。 YMMV.

还有另一种方法,不需要固定但需要更多的机器代码:

void ManagedMethod(int% n)
{
    int copy = n;
    NativeMethod(copy);
    n = copy;
}

之所以可行,是因为局部变量具有堆栈存储空间,因此不会被垃圾收集器移动。没有赢得任何风格的优雅点,但我通常自己使用,估计固定的副作用并不那么容易。但是,真的,不要害怕 pin_ptr<>。