簡體   English   中英

編組包含指向數組的指針的結構

[英]Marshal a struct containing pointer to array

如何正確編組此 C 結構,其中包含指向數組的指針和指向 C# 中的指針成員的指針,以便與第 3 方 dll 一起使用?

C:

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

是否都只是IntPtr然后你需要分配未損壞的 memory,將數據復制到其中並固定它? 如果是這樣,你會怎么做? 該結構通過 dll 內部的 function 進行初始化。

在 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 提供了分配和釋放這些結構的方法。

鑒於您的結構,我們可以:

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 中分配的someStruct否則您將有 memory 泄漏!

關於extended_data ,我無法為您提供幫助,因為您還沒有告訴我們它應該是什么,

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


}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM