【发布时间】:2016-07-28 23:11:31
【问题描述】:
我正在尝试关注this question 的答案
我的结构在 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。
提前致谢。
【问题讨论】:
-
出于好奇,如果将
[StructLayout(LayoutKind.Sequential)]更改为[StructLayout(LayoutKind.Sequential, Pack=5)]会发生什么? -
Pack = 5 不是一个有效值,我也尝试过 1、2、4、8 个值而没有变化。
-
我想知道...如果您将 IntPtr 更改为 UIntPtr 并将 ToInt32 的所有引用更改为 UInt32。我知道有时它看起来并不重要,但是......
-
当我切换到 UIntPtr 时,PtrToStructure 对我大喊大叫。我尝试使用 .ToPointer 但它仍然出错。
-
@DavidHeffernan 托管大小的结构是 32,非托管大小的结构是 32。你如何确定 36?