本文介绍了传递一个结构在C#中使用Marshal.StructureToPtr C ++ API的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的API C ++编写的在我的代码(在C#书面方式)。
API需要为指针的结构参数。
结构由内部S和字符数组:
例如:

I am using API written in C++ in my code (writting in C#). API requires a parameter as Pointer to Structure.The Structure consists of "Int"s and Char Arrays:for example

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



我不能直接传递结构指针API,因为在这种情况下,我我得到的错误是指针不能引用封结构。 。代码获得成功编译但这个错误是当我执行(调试)代码

I can not directly pass the structure pointer to API because in that case, I am getting error as "Pointers cannot reference Marshaled structures". Code get compiled successfully but this Error comes when I execute (Debug) the code.

现在我有两个选择:
1: - 通过参考传递结构:我想问问是否需要结构指针的API可以接收地址时,我被裁判传递结构。需要注意的是API将在字符[]数据返回数据

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. Note that API will return Data in "Char[] Data".

2日: - 使用Marshal.StructureToPtr:这将结构指针转换为IntPtr的。同样的怀疑是一样的,这会否API正确接收呢?

2nd:- Using Marshal.StructureToPtr: This will convert Structure Pointer to IntPtr. Again the Doubt is same, Will that API receive it correctly?

感谢您的时间!

问候,
Swanand

Regards,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;
}

这篇关于传递一个结构在C#中使用Marshal.StructureToPtr C ++ API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-31 09:47