DllImport和返回参数

时间:2012-11-01 19:23:51

标签: pinvoke

我正在进行硬件测试。我们的测试框架是用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也会正确更新吗?我听说在这种情况下managedStatusnativeStatus没有指向相同的内存。 Marshaler在调用完成后只返回nativeState的副本。如果不是解决方案是什么?我是否需要使用unsave关键字并将我的代码创建并执行fixed{}块中的序列?

[DllImport(@"native.dll", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)]
internal static unsave extern Byte someMethod(UInt32 * managedStatus)

1 个答案:

答案 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
}