简体   繁体   English

使用C#中的Marshal.StructureToPtr将结构传递给C ++ API

[英]Passing a Structure to C++ API using Marshal.StructureToPtr in C#

I am using API written in C++ in my code (writting in C#). 我在我的代码中使用C ++编写的API(用C#编写)。 API requires a parameter as Pointer to Structure. API需要一个参数作为指向结构的指针。 The Structure consists of "Int"s and Char Arrays: for example 结构由“Int”和Char Arrays组成:例如

 unsafe public struct ToBePassed 
    { 
        Int32 Num1;
        Int32 Num2; 
        Char[] Data; // or fixed Char Data[255];
    }

I can not directly pass the structure pointer to API because in that case, I am getting error as "Pointers cannot reference Marshaled structures". 我不能直接将结构指针传递给API,因为在这种情况下,我收到错误,因为“指针不能引用Marshaled结构”。 Code get compiled successfully but this Error comes when I execute (Debug) the code. 代码编译成功但是当我执行(调试)代码时会出现此错误。

Now I have two options: 1st:- Passing Structure by Ref: I want to ask does an API requiring A Structure Pointer can receive the address when I pass the structure by ref. 现在我有两个选择:第一: - 通过参考传递结构:我想问一下当我通过ref传递结构时,需要结构指针的API是否可以接收地址。 Note that API will return Data in "Char[] Data". 请注意,API将在“Char [] Data”中返回Data。

2nd:- Using Marshal.StructureToPtr: This will convert Structure Pointer to IntPtr. 第二: - 使用Marshal.StructureToPtr:这会将结构指针转换为IntPtr。 Again the Doubt is same, Will that API receive it correctly? 怀疑是相同的,API会正确接收吗?

Thanks for Your Time! 谢谢你的时间!

Regards, Swanand 此致,Swanand

If it only requires pointer, you can allocate some unmanaged memory, marshal the structure to the memory, and pass that pointer to your function. 如果它只需要指针,您可以分配一些非托管内存,将结构编组到内存中,并将该指针传递给您的函数。 Then afterwards you could marshal back to the structure (if you wish) and free the memory. 然后你可以编组回到结构(如果你愿意)并释放内存。 Before you marshal anything, you need to properly define the structure. 在编组任何内容之前,您需要正确定义结构。 Something like this: 像这样的东西:

[StructLayout(
    LayoutKind.Sequential,      //must specify a layout
    CharSet = CharSet.Ansi)]    //if you intend to use char
public struct ToBePassed
{
    public Int32 Num1;
    public Int32 Num2;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 255)]
    public Char[] Data;    //specify the size using MarshalAs
}

[DllImport("...")]
public static extern void APICall(IntPtr argPtr);


public static void CallFunction(ToBePassed managedObj)
{
    IntPtr unmanagedAddr = Marshal.AllocHGlobal(Marshal.SizeOf(managedObj));

    Marshal.StructureToPtr(managedObj, unmanagedAddr, true);

    APICall(unmanagedAddr);

    Marshal.PtrToStructure(unmanagedAddr, managedObj);

    Marshal.FreeHGlobal(unmanagedAddr);
    unmanagedAddr = IntPtr.Zero;
}

[edit] [编辑]
To simulate variable length arrays, allocate unmanaged memory within the structure and initialize as usual. 要模拟可变长度数组,请在结构中分配非托管内存并像往常一样进行初始化。

[StructLayout(LayoutKind.Sequential)]
public struct SomeStruct
{
    public Int32 X;
    public Int32 Y;
}

[StructLayout(LayoutKind.Sequential)]
public struct VLA
{
    public Int32 intArrayLength;
    public Int32 SomeStructArrayLength;
    public IntPtr intArray;
    public IntPtr SomeStructArray;
}

public static VLA CreateVLA(int[] intArray, SomeStruct[] SomeStructArray)
{
    var vla = new VLA()
    {
        intArrayLength = intArray.Length,
        SomeStructArrayLength = SomeStructArray.Length,
        intArray = Marshal.AllocHGlobal(intArray.Length * Marshal.SizeOf(typeof(int))),
        SomeStructArray = Marshal.AllocHGlobal(SomeStructArray.Length * Marshal.SizeOf(typeof(SomeStruct))),
    };
    Marshal.Copy(intArray, 0, vla.intArray, intArray.Length);
    //there's no overload to copy arbitrary arrays, do it manually
    for (int i = 0; i < SomeStructArray.Length; i++)
    {
        Marshal.StructureToPtr(
            SomeStructArray[i],
            vla.SomeStructArray + i * Marshal.SizeOf(typeof(SomeStruct)),
            true);
    }
    return vla;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM