Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
375 views
in Technique[技术] by (71.8m points)

c# - Marshal a struct containing pointer to array

How to correctly marshal this C struct with pointer to array and pointer to pointer members in C# for use with 3rd party dll?

C:

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

Is it all just IntPtr and then you need to allocate the un-mamaged memory, copy data into it, and pin it? How would you do this if it's the case? The struct gets initialized through a function inside dll.

In python this is how I'd wrap and use this struct:

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

Trying to find a C# equivalent of this code.

extended_data is a bonus if you know how to deal with it, it's dynamic size and I am not sure how I'd get its size.

A real example would be

The .dll provides methods to allocate and free these structures.

question from:https://stackoverflow.com/questions/65855005/marshal-a-struct-containing-pointer-to-array

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Given your struct, we could:

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);

Then:

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();
}

Note that at the end you should call some C method to free the memory allocated in someStruct otherwise you'll have a memory leak!

I can't help you about extended_data, because you haven't told us what it should be,


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...