如何将 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++ 代码中分配数组,编组类型

创建要在 C# 中编组的 C++ Dll 的最佳实践 [关闭]

C#:指向结构内部结构的指针