如何将一个C数组映射到C#?

3
我的问题与尝试从C#调用一个由C编写的函数有关。我查看了附带C库的头文件,以了解函数在C dll中的存在方式。以下是我看到的内容:
C代码(用于名为“LocGetLocations”的函数):
typedef enum {
    eLocNoError,
    eLocInvalidCriteria,
    eLocNoMatch, 
    eLocNoMoreLocations,
    eLocConnectionError, 
    eLocContextError,
    eLocMemoryError
} tLocGetStatus; 

typedef void *tLocFindCtx;

typedef void *tLocation;    

PREFIX unsigned int POSTFIX LocGetLocations
(
    tLocFindCtx pCtx, 
    tLocation *pLoc,
    unsigned int pNumLocations,
    tLocGetStatus *pStatus
);

在C#中,我有以下代码:
[DllImport(@"VertexNative\Location.dll")]
public static extern uint LocGetLocations(IntPtr findContext, out byte[] locations, uint numberLocations, out int status);

问题是我不太知道怎样在 C# 中处理 pLoc 参数。我把它转换成了字节数组,但我不确定这样是否正确。C 库文档说明该参数是一个指向句柄数组的指针。如何在 C# 端获取一个数组并访问它的数据?C 语言中给出的示例代码如下:
tLocation lLocation[20];

// other stuff

LocGetLocations(lCtx, lLocation, 20, &lStatus)

任何帮助都将不胜感激!

2
如果它是一个句柄数组,你需要将其转换为 IntPtr 数组。 - Jim Mischel
请参阅 http://pinvoke.net/index.aspx 获取大量示例。 - Jonathan Allen
2个回答

2

通常情况下,唯一需要考虑的是参数的大小。据我回忆,C语言中的枚举是整数类型,因此您可以直接使用它。或者更好的方法是,在C#中重新创建相同的枚举类型,我认为这会奏效。记住,当处理复杂结构时,需要使用属性来告诉框架有关成员所需对齐方式的信息。


1
最终,这个签名是有效的:
[DllImport(@"VertexNative\Location.dll")]
public static extern uint LocGetLocations(IntPtr findContext, [Out] IntPtr[] locations, uint numberLocations, out int status);

我可以这样调用它(需要一些重构):

IntPtr[] locations = new IntPtr[20];
int status;
// findContext is gotten from another method invocation
uint result = GeoCodesNative.LocGetLocations(findContext, locations, 20, out status);

感谢您的帮助!


注意,我认为是我的使用“out”关键字让我陷入困境。将其删除使我走得更远。这很有道理,因为数组本来就是引用类型,不需要输出以将局部变量分配给方法的新值。 - Nick R.
@Nick:你想要的是将 [OutAttribute](或者只用 [Out])添加到 IntPtr[] locations 上。这样告诉了 marshaller 仅在返回时复制,而不是在进出时都复制。这可以避免发生一次不必要的块复制。 - Tergiver
将out添加到IntPtr[]位置会导致运行时错误。 - Nick R.
我修改了你的答案以展示我的意思。不是 out,而是 [Out] - Tergiver
2
out是一个参数修饰符。[Out]是一个属性,具体来说是System.Runtime.InteropServices.OutAttribute。这个属性不是由编译器检查的,而是由CLR marshaller在运行时检查的。Marshalling意味着分配非托管内存,从托管内存复制到非托管内存,调用非托管函数,然后从非托管内存复制回托管内存。[In][Out]属性允许您控制默认情况下发生的复制。 - Tergiver
非常好。添加 [Out] 使 C 方法返回值,否则返回为空。谢谢! - Nick R.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接