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

2024-03-10

我在我的代码中使用用 C++ 编写的 API(用 C# 编写)。 API 需要一个参数作为结构指针。 该结构由“Int”和 Char 数组组成: 例如

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

我无法直接将结构指针传递给 API,因为在这种情况下,我会收到错误“指针无法引用封送结构”。代码已成功编译,但当我执行(调试)代码时出现此错误。

现在我有两个选择: 第一:- 通过引用传递结构:我想问当我通过引用传递结构时,需要结构指针的 API 是否可以接收地址。请注意,API 将返回“Char[] Data”中的数据。

第二:- 使用 Marshal.StructureToPtr:这会将结构指针转换为 IntPtr。同样的疑问是,该 API 会正确接收它吗?

谢谢你的时间!

问候, 斯瓦南德


如果它只需要指针,您可以分配一些非托管内存,将结构封送到内存,然后将该指针传递给您的函数。然后,您可以编组回结构(如果您愿意)并释放内存。在编组任何内容之前,您需要正确定义结构。像这样的东西:

[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]
要模拟可变长度数组,请在结构内分配非托管内存并照常初始化。

[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;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 C# 中使用 Marshal.StructureToPtr 将结构传递给 C++ API 的相关文章

随机推荐