簡體   English   中英

使用C#中的Marshal.StructureToPtr將結構傳遞給C ++ API

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

我在我的代碼中使用C ++編寫的API(用C#編寫)。 API需要一個參數作為指向結構的指針。 結構由“Int”和Char Arrays組成:例如

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

我不能直接將結構指針傳遞給API,因為在這種情況下,我收到錯誤,因為“指針不能引用Marshaled結構”。 代碼編譯成功但是當我執行(調試)代碼時會出現此錯誤。

現在我有兩個選擇:第一: - 通過參考傳遞結構:我想問一下當我通過ref傳遞結構時,需要結構指針的API是否可以接收地址。 請注意,API將在“Char [] Data”中返回Data。

第二: - 使用Marshal.StructureToPtr:這會將結構指針轉換為IntPtr。 懷疑是相同的,API會正確接收嗎?

謝謝你的時間!

此致,Swanand

如果它只需要指針,您可以分配一些非托管內存,將結構編組到內存中,並將該指針傳遞給您的函數。 然后你可以編組回到結構(如果你願意)並釋放內存。 在編組任何內容之前,您需要正確定義結構。 像這樣的東西:

[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;
}

[編輯]
要模擬可變長度數組,請在結構中分配非托管內存並像往常一樣進行初始化。

[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