我有一个 C++/CLI 方法 ManagedMethod
,它有一个输出参数,该参数将由 native 方法修改,如下所示:
// 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
的值就按照我的预期被修改了。到目前为止,我能够编译此代码的唯一方法是在 ManagedMethod
中使用 pin_ptr
,因此固定实际上是正确/唯一的方法这?或者是否有更优雅的方式将 n
传递给 NativeMethod
?
最佳答案
是的,这是正确的方法。在 CLR 内部进行了高度优化,该变量获得 [pinned] 属性,因此 CLR 知道它存储了一个指向不应移动的对象的内部指针。与 GCHandle::Alloc() 不同,pin_ptr<> 可以在不创建另一个句柄的情况下完成此操作。表中显示,编译方法时会产生抖动,GC 使用该表来知道在哪里寻找对象根。
只有当垃圾回收与 NativeMethod() 运行的同时发生时,这才有意义。在实践中并不经常发生,您必须在程序中使用线程。 YMMV。
还有另一种方法可以做到这一点,不需要固定,但需要更多的机器代码:
void ManagedMethod(int% n)
{
int copy = n;
NativeMethod(copy);
n = copy;
}
这是有效的,因为局部变量具有堆栈存储,因此不会被垃圾收集器移动。风格上没有赢得任何优雅点,但我自己通常使用的,估计固定的副作用并不那么容易。但是,实际上,不要害怕 pin_ptr<>。
关于c++-cli - C++/CLI 方法调用 native 方法来修改 int - 需要 pin_ptr?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35805303/