如何将 C 指针编组到 C# 结构数组
Posted
技术标签:
【中文标题】如何将 C 指针编组到 C# 结构数组【英文标题】:How to Marshal C pointer to C# array of struct 【发布时间】:2014-06-10 15:19:52 【问题描述】:我正在尝试将来自 c dll 的指针转换为其等效的 C# struct 数组。
C 代码
RECORD locked[MAX+1]; //MAX is a constant
typedef struct
State state; //enum
unsigned long allocated;
unsigned long lastUsed;
unsigned int useCount;
RECORD;
API RECORD* __stdcall GetLocks( char* password )
if(strcmp(password, secret) == 0)
return locked;
else
return 0;
C#代码
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] // Pretty sure CharSet isnt actually needed here
public struct RECORD
public State state;
public UInt32 allocated;
public UInt32 lastUsed;
public UInt16 useCount;
[DllImport("gatewayapi.dll", CharSet = CharSet.Ansi)] // or here
static extern IntPtr GetLocks(string password);
public RECORD[] GetLocks(string password)
RECORD[] recs = new RECORD[MAX+1];
recs =(RECORD[])Marshal.PtrToStructure( GetLocks(password), typeof(RECORD[]));
if (recs.Length == 0)
throw new Exception();
return recs;
不幸的是,上面返回了一个 MissingMethodException -> 没有为此对象定义无参数构造函数。
所以我对 Marshalling 来说是 100% 的新手,并且希望得到一些关于如何将我从 C 接收到的指针转换为它所代表的实际 C# 结构数组的建议。
谢谢
【问题讨论】:
你不能在数组类型上使用 Marshal.PtrToStructure(),你必须一次做一个。 useCount 字段的类型错误,它是 int。 【参考方案1】:鉴于最初发布的 C 代码,这是我想出的不需要在不安全模式下编译代码的答案:
[DllImport("gatewayapi.dll", CharSet = CharSet.Ansi)]
static extern IntPtr AMTgetLocks(string password);
public RECORD[] GetLocks(string password)
var channels = new RECORD[MAXCHANS + 1];
try
var c = AMTgetLocks(password);
var crSize = Marshal.SizeOf(typeof(RECORD));
for (int i = 0; i < MAXCHANS + 1; i++)
channels[i] = (CHANNELRECORD)Marshal.PtrToStructure(c, typeof(RECORD));
c = new IntPtr(c.ToInt64() + crSize);
catch (Exception)
throw new Exception();
if (channels.Length == 0)
throw new Exception();
return channels;
【讨论】:
以上是关于如何将 C 指针编组到 C# 结构数组的主要内容,如果未能解决你的问题,请参考以下文章
如何将指向 char[256] 数组的指针从 C++ 编组到 C#
P/Invoke 编组和解组 C# 和非托管 DLL 之间的二维数组、结构和指针
如何在 C# 中编组指向一系列以 null 结尾的字符串的指针?
在 C# 中传递 IntPtr 指针后,在非托管 C++ 代码中分配数组,编组类型