我正在进行硬件测试。我们的测试框架是用C#编写的,但我们使用本机dll与硬件进行通信。
假设我们有一个C ++方法:
unsigned char someMethod(unsigned long * nativeStatus)
反过来执行嵌入式命令并在命令完成时返回状态。
要使用它,我们创建一个包装器
[DllImport(@"native.dll", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)]
internal static extern Byte someMethod(ref UInt32 managedStatus)
这很好用。但是有一种情况是someMethod
调用实际上没有执行命令,只是将它添加到序列中。然后可以通过发送特殊命令ExecuteSequence
来执行序列。在执行序列时,C ++代码仅通过将数据复制到nativeStatus
指针引用的内存中来更新nativeStatus
。随着序列的完成,ExecuteSequence
方法返回。目前,我确信所有数据(本例中为nativeStatus
)都已更新。我的managedStatus
也会正确更新吗?我听说在这种情况下managedStatus
和nativeStatus
没有指向相同的内存。 Marshaler在调用完成后只返回nativeState
的副本。如果不是解决方案是什么?我是否需要使用unsave关键字并将我的代码创建并执行fixed{}
块中的序列?
[DllImport(@"native.dll", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)]
internal static unsave extern Byte someMethod(UInt32 * managedStatus)
答案 0 :(得分:0)
所以你需要的是一个可变位置,它在一段时间内不会改变。
是的,您可以使用fixed{}
。
或者,您可以固定该变量:
private uint g_Pinnable = 0;
...
var gc = System.Runtime.InteropServices.GCHandle.Alloc(g_Pinnable, System.Runtime.InteropServices.GCHandleType.Pinned);
try
{
// Pass 'ref g_Pinnable' to API
// Then execute the sequence.
}
finally
{
gc.Free(); // Reference to g_Pinnable may be invalid after this point
}