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

时间:2021-01-23 01:59:12

标签: c# pointers struct marshalling

如何使用指向数组的指针和指向 C# 中的指针成员的指针正确编组此 C 结构以与 3rd 方 dll 一起使用?

C:

typedef struct SomeStruct {
    uint8_t *data[8];
    int size[8];
    uint8_t **extended_data;
};

这一切只是IntPtr,然后您需要分配未管理的内存,将数据复制到其中并固定吗?如果是这样,你会怎么做?该结构体通过 dll 中的函数进行初始化。

在 python 中,这是我包装和使用这个结构的方式:

Python:

class SomeStruct(Structure):
    _fields_ = [
         ('data', POINTER(c_uint8) * 8),
         ('size', c_int * 8),
         ('extended_data', POINTER(POINTER(c_uint8)))
    ]

# example use 1
dll = ctypes.CDLL("lib.dll")
some_struct = SomeStruct()
dll.init_struct(ctypes.byref(some_struct))

# or example 2
alloc_struct_fce = dll.alloc_struct
alloc_struct_fce.restype = ctypes.POINTER(SomeStruct)   # specify return type
some_struct_ptr = alloc_struct_fce()    # this gets passed to other dll functions
dll.some_processing(some_struct_ptr)
some_struct = some_struct_ptr.contents    # dereference the pointer

试图找到与此代码等效的 C#。

extended_data 如果你知道如何处理它是一个奖励,它是动态大小,我不确定如何获得它的大小。

一个真实的例子是

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

2 个答案:

答案 0 :(得分:0)

根据您的结构,我们可以:

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;
SomeStructMethod(out someStruct);

for (int i = 0; i < someStruct.data.Length; i++)
{
    var array = new byte[someStruct.size[i]];
    Marshal.Copy(someStruct.data[i], array, 0, array.Length);

    Console.Write("> ");

    for (int j = 0; j < array.Length; j++)
    {
        Console.Write($"{array[j]} ");
    }

    Console.WriteLine();
}

注意,最后你应该调用一些 C 方法来释放 someStruct 中分配的内存,否则你会发生内存泄漏!

关于extended_data,我无法为您提供帮助,因为您还没有告诉我们它应该是什么,

答案 1 :(得分:0)

我将使用以下基于 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;
    }


}
相关问题