PInvoke-从指针封送一个结构数组

本文关键字:一个 结构 数组 指针 PInvoke- | 更新日期: 2023-09-27 17:59:05

我正试图按照这个问题的答案

我的结构在C 中看起来像这样

typedef struct drive_info_t {
    unsigned char drive_alias[32];
} drive_info_t;

我的函数在C 中是这样的

unsigned int get_drive_info_list(drive_info_t **list, unsigned int *item_count) {
    //fill list in native C
    //print out in native C
    printf("list.alias - %s'r'n",list[i]->drive_alias);
}

我的C#结构看起来像这个

[StructLayout(LayoutKind.Sequential)]
public struct drive_info_t
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
    public byte[] drive_alias;
}

我的C#函数声明看起来像这个

[DllImport("mydll.dll", EntryPoint = "get_drive_info_list", CallingConvention = CallingConvention.Cdecl)]
public static extern uint GetDriveInfoList(out System.IntPtr ptr_list_info, out System.IntPtr ptr_count);

我正在调用类似的C#函数

IntPtr ptr_list_info = IntPtr.Zero;
IntPtr ptr_cnt = IntPtr.Zero;
ret = api.GetDriveInfoList(out ptr_list_info, out ptr_cnt);

我正在整理像这样的返回指针

nAlloc = ptr_cnt.ToInt32();
int szStruct = Marshal.SizeOf(typeof(api.drive_info_t));
api.drive_info_t[] localStructs = new api.drive_info_t[nAlloc];
for (int i = 0; i < nAlloc; i++)
{
    localStructs[i] = (api.drive_info_t)Marshal.PtrToStructure(ptr_list_info, typeof(api.drive_info_t));
    ptr_list_info = new IntPtr(ptr_list_info.ToInt32() + (szStruct));
}

打印类似的结构别名

for (uint i = 0; i < localStructs.Length; i++)
{    
    Console.WriteLine("list.alias - {0}", System.Text.Encoding.Default.GetString(localStructs[i].drive_alias));
}

谢谢你和我在一起。

这就是我在C#控制台应用程序上的输出。你可以看到本机的C dll打印到控制台它的值,但我的封送处理在某个地方出错了:

======================== C values ============================
list.alias - drv1
list.alias - drv2
list.alias - drv3
list.alias - drv4
======================== C# values ============================
list.alias - drv1
list.alias - o£Q95drv2
list.alias -         o£Q95drv3
list.alias -                 o£Q95drv4

我不知道这些垃圾文本和偏移量是从哪里来的。

我负责.Net方面,如果需要,其他团队成员可以根据需要更改本机C,但本机C的更改需要跨平台OSX/Windows/Linux。

提前谢谢。

PInvoke-从指针封送一个结构数组

这是一个完美的例子,说明了为什么参数类型不定义接口。考虑

drive_info_t **list

这可以是指向结构数组的指针。在这种情况下,数组大概是由被调用者分配的。这就是为什么使用指向数组的指针而不是数组。

或者它可以是指向结构的指针数组。在这里,数组将由调用者分配,结构可以由被调用者或调用者分配。我们无从得知。

我们可以看出,您的接口接受一个指向struct的指针数组。看看这个代码:

list[i]->drive_alias

很明显,list是指向struct的指针数组。

这告诉您的代码是错误的。您使用了错误的模板,因为您错误地识别了语义。下一步是返回接口的文档和任何调用代码的示例,以准确地了解语义。谁分配和处置什么。

几乎可以肯定的是,您将使用IntPtr[]来封送数组,但除此之外,我们不可能说出会发生什么。我猜调用者分配结构,但不依赖于猜测。阅读文档和示例调用代码。

除此之外,根据函数的语义,第二个参数应该是ref uintout uint。再说一遍,这是我们无法解决的问题。