C# 封送包含指向数组指针的结构

C# 封送包含指向数组指针的结构,c#,pointers,struct,marshalling,C#,Pointers,Struct,Marshalling,如何在C#中使用指向数组的指针和指向指针成员的指针正确封送此C结构,以便与第三方dll一起使用 C: typedef struct SomeStruct{ uint8_t*数据[8]; 整数大小[8]; uint8\u t**扩展数据; }; 这一切都只是IntPtr,然后您需要分配未配置的内存,将数据复制到内存中,并将其固定?如果是这样的话,你会怎么做?结构通过dll中的函数初始化 在python中,我将包装并使用此结构: Python: 类SomeStruct(结构): _字段=[ (“数

如何在C#中使用指向数组的指针和指向指针成员的指针正确封送此C结构,以便与第三方dll一起使用

C:

typedef struct SomeStruct{
uint8_t*数据[8];
整数大小[8];
uint8\u t**扩展数据;
};
这一切都只是
IntPtr
,然后您需要分配未配置的内存,将数据复制到内存中,并将其固定?如果是这样的话,你会怎么做?结构通过dll中的函数初始化

在python中,我将包装并使用此结构:

Python:

类SomeStruct(结构):
_字段=[
(“数据”,指针(c_uint8)*8),
(“尺寸”,c_int*8),
('extended_data',指针(指针(c_uint8)))
]
#示例1
dll=ctypes.CDLL(“lib.dll”)
some_struct=SomeStruct()
dll.init_结构(ctypes.byref(some_结构))
#或例2
alloc_struct_fce=dll.alloc_struct
alloc_struct_fce.restype=ctypes.POINTER(SomeStruct)#指定返回类型
some_struct_ptr=alloc_struct_fce()#这会传递给其他dll函数
dll.some_processing(some_struct_ptr)
some_struct=some_struct_ptr.contents#取消对指针的引用
试图找到此代码的C#等价物

extended_data
如果您知道如何处理它,它是动态大小的,我不确定如何获得它的大小,那么它就是一个额外的功能

一个真正的例子是

  • 连同

.dll提供了分配和释放这些结构的方法。

给定您的结构,我们可以:

struct SomeStruct
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
    public IntPtr[] data;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
    public int[] size;

    public IntPtr extended_data;
}

// I don't know the calling convention of your C method... You didn't show
// us its signature. It could be cdecl or stdcall
[DllImport(@"somedll.dll", CallingConvention = CallingConvention.Cdecl /* or StdCall */)]
public static extern void SomeStructMethod(out SomeStruct someStruct);
然后:

SomeStruct SomeStruct;
someStruct方法(out someStruct);
for(int i=0;i”;
for(int j=0;j
注意,最后应该调用一些C方法来释放在
someStruct
中分配的内存,否则会出现内存泄漏


我无法帮助您了解扩展数据,因为您没有告诉我们它应该是什么,

我将使用以下基于xanatos代码的代码:

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

namespace ConsoleApplication1
{
    class Program
    {
        [DllImport(@"somedll.dll", CallingConvention = CallingConvention.Cdecl /* or StdCall */)]
        public static extern void SomeStructMethod(out SomeStruct someStruct);
        static void Main(string[] args)
        {
            SomeStruct someStruct;
            SomeStructMethod(out someStruct);

            byte[] data = new byte[8];
            Marshal.Copy(someStruct.data, data, 0, 8);

            byte[][] extendedData = new byte[8][];
            for(int i = 0; i < 8; i++)
            {
                extendedData[i] = new byte[someStruct.size[i]];
                Marshal.Copy(someStruct.extended_data[i], extendedData[i], 0, someStruct.size[i]);

            }
        }
    }
  
    struct SomeStruct
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public IntPtr data;

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public int[] size;

        public IntPtr[] extended_data;
    }


}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Runtime.InteropServices;
命名空间控制台应用程序1
{
班级计划
{
[DllImport(@“somedll.dll”,CallingConvention=CallingConvention.Cdecl/*或StdCall*/)]
公共静态外部void SomeStructMethod(out SomeStruct SomeStruct);
静态void Main(字符串[]参数)
{
SomeStruct SomeStruct;
someStruct方法(out someStruct);
字节[]数据=新字节[8];
Marshal.Copy(someStruct.data,data,0,8);
字节[][]扩展数据=新字节[8][];
对于(int i=0;i<8;i++)
{
extendedData[i]=新字节[someStruct.size[i]];
Marshal.Copy(someStruct.extended_data[i],extendedData[i],0,someStruct.size[i]);
}
}
}
结构SomeStruct
{
[Marshallas(UnmanagedType.ByValArray,SizeConst=8)]
公共IntPtr数据;
[Marshallas(UnmanagedType.ByValArray,SizeConst=8)]
公共int[]大小;
公共IntPtr[]扩展_数据;
}
}

这取决于谁分配
data
extended\u data
所指的内存。调用方(C#)或被调用方(dll)。如果它是被调用方(dll),那么
IntPtr
,如果它是调用方,也许您可以传递
byte[][]
,但我不确定。代码使用的是Windows分配方法,请参阅下面的等效c代码:。您正在读取数据,那么扩展数据的大小是多少?通常是这样的结构,第一个数字是扩展数据的第二个数字的长度。@jdweng yes该结构记录了8个数组中每个数组的大小。我更新了问题。但是,对于
extended_数据
不确定。@xanatos它是被调用方(dll)。我怀疑这是
IntPtr
,我面临的麻烦是获取这样的结构的内容。来自python,这一切都令人困惑,因为每个示例的处理方式都有点不同,有很多在线示例,但没有一个与我的完全相同。谢谢,这真的帮助我开始理解它是如何工作的,以及为什么它如此依赖于.dll代码。我更新了这个问题以提供真实的示例,我认为调用约定是Cdecl。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    class Program
    {
        [DllImport(@"somedll.dll", CallingConvention = CallingConvention.Cdecl /* or StdCall */)]
        public static extern void SomeStructMethod(out SomeStruct someStruct);
        static void Main(string[] args)
        {
            SomeStruct someStruct;
            SomeStructMethod(out someStruct);

            byte[] data = new byte[8];
            Marshal.Copy(someStruct.data, data, 0, 8);

            byte[][] extendedData = new byte[8][];
            for(int i = 0; i < 8; i++)
            {
                extendedData[i] = new byte[someStruct.size[i]];
                Marshal.Copy(someStruct.extended_data[i], extendedData[i], 0, someStruct.size[i]);

            }
        }
    }
  
    struct SomeStruct
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public IntPtr data;

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public int[] size;

        public IntPtr[] extended_data;
    }


}