将结构的成员转换为 IntPtr

Converting member of a structure to an IntPtr

我正在为以下 C++ 函数编写绑定:

AvailableNodes(void* handle, Node** headNode)

Connect(void* handle, char* nodeId)

AvailableNodes 函数将 return 使用以下 Struct 的节点列表:

typedef struct Node
{
    struct Node    *nextNode;
    unsigned long   nodeID;
    char            data[256];
} Node;

创建必要的绑定后,我在 C# 中得到以下结构:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct Node
{
    public ulong id;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
    public char[] data;
    public IntPtr nextNode;
}

为了继续前进,我必须将指向 Node.data 的指针作为参数发送给 Connect 函数,但是,在编组之后(使用 Marshal.PtrToStructure),如果我尝试发送它,我得到一个 Access violation 相反。

有什么想法吗?

试试这样的代码。我更改了 nextNode 在结构中的顺序,因此 c++ 和 c# 结构的顺序相同。我假设在根目录下有一个节点数组和一个 link 节点列表。我还假设节点是从 C++ 返回的。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    class Program
    {
        [DllImport("Connect", CallingConvention = CallingConvention.Cdecl)]
        static void Connect(out uint handle, [MarshalAs(UnmanagedType.AnsiBStr)] string nodeId);

        [DllImport("AvailableNodes", CallingConvention = CallingConvention.Cdecl)]
        static void AvailableNodes(uint handle, out IntPtr headNode);

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct Node
        {
            public IntPtr nextNode;
            [MarshalAs(UnmanagedType.U4)]
            public uint id;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
            public char[] data;

        }

        static void Main(string[] args)
        {
            string id = "abc";
            uint handle = 0;
            Connect(out handle, id);

            IntPtr ptr = IntPtr.Zero;
            AvailableNodes(handle, out ptr);

            List<List<Node>> nodes = null;
            List<Node> listNode;

            //enumerate through array of nodes
            while (ptr != IntPtr.Zero)
            {
                listNode = new List<Node>();
                if (nodes == null) nodes = new List<List<Node>>();
                nodes.Add(listNode);
                Node newNode = (Node)Marshal.PtrToStructure(ptr, typeof(Node));
                listNode.Add(newNode);
                // enumerate through link list
                while (newNode.nextNode != IntPtr.Zero)
                {
                    newNode = (Node)Marshal.PtrToStructure(ptr, typeof(Node));
                    listNode.Add(newNode);
                }
                ptr += 4;  //I think 4 is correct since a ptr is 4 bytes
            }
        }
    }
}