2

我有一个 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返回后, 的值n已按我的预期进行了修改。到目前为止,我能够编译它的唯一方法是使用pin_ptrinside ManagedMethod,那么实际上 pinning 是正确/唯一的方法吗?还是有更优雅的传递n方式NativeMethod

4

1 回答 1

2

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

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

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

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

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

于 2016-03-04T21:25:25.170 回答