无法从Mono中的非托管代码解组结构

时间:2012-02-17 02:10:10

标签: mono marshalling

问题:

我可以成功地将具有根元素和数组元素的结构编组为非托管代码,但无法获取根元素数据(数组元素返回正确)。我尝试了很多方法,但迄今为止都没有。这是下面最简单的一个。

我在http://www.mono-project.com/Interop_with_Native_Libraries阅读并认为我正在做的一切正确(但显然不是; - )

实施

C#声明:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct Vector3
{
    public float x;
    public float y;
    public float z;
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct MeshData
{
    [MarshalAs(UnmanagedType.LPArray)]
    public Vector3[] vertices;
    public int verticeCount;
}

[DllImport("MeshPlugin")]
private static extern bool ImportMesh([In, Out, MarshalAs(UnmanagedType.LPStruct)] MeshData meshData);

原生C声明:

#pragma pack(1)
typedef struct VECTOR3
{
    float x;
    float y;
    float z;
} VECTOR3;

#pragma pack(1)
typedef struct MESHDATA
{
    VECTOR3 *vertices;
    int verticeCount;
} MESHDATA;

从C#调用如下:

<defined vertices and length...>

MeshData meshData = new MeshData();
meshData.vertices = mesh.vertices; // note that vertices[0].x = 111
meshData.verticeCount = 1;
ImportMesh(meshData); // calls native function
Debug.Log(meshData.vertices[0].x); // prints  222 which is correct, so array got marshaled back okay
Debug.Log(meshData.verticeCount); //  **prints 1 which is incorrect** so the int element did not come back okay

原生实施:

bool ImportMesh(MESHDATA *meshData)
{
    printf("%f", meshData->vertices[0].x); // prints 111 which is correct
    meshData->vertices[0].x = 222; // change to see if it gets back okay
    printf("%d", meshData->verticeCount); // prints 1 which is correct
    meshData->verticeCount = 2; // change to see if it gets back okay
    return true;
}

问题是结构的子数组值是否正确返回,但主结构元素不是。

我也在C#中试过这个:

[DllImport("MeshPlugin")]
private static extern bool ImportMesh(IntPtr meshData);

int size = Marshal.SizeOf(typeof(MeshData));
IntPtr pMeshData = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(meshData, pMeshData, false);
ImportMesh(pMeshData);
meshData = (MeshData)(Marshal.PtrToStructure(pMeshData, typeof(MeshData)));
Marshal.FreeHGlobal(pMeshData);     

这一个在返回时崩溃严重(但是日志显示本机代码已执行并在本机端打印了正确的值)。

我尝试过使用属性修饰器等的其他排列,但是单声道编译器建议删除一些属性,因为我不需要这样做。

我一直在谷歌上搜索这个问题2天,并且非常感谢任何帮助!

1 个答案:

答案 0 :(得分:2)

我没试过这个,但这是我第一次尝试这样做的方法:

[DllImport("MeshPlugin")]
private static extern bool ImportMesh(ref MeshData meshData);

如果它仍然不起作用,我会尝试将struct声明更改为:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct MeshData
{
    public IntPtr vertices;
    public int verticeCount;
}
MeshData meshData = new MeshData();
meshData.vertices = Marshal.AllocHGlobal (...);
// copy vertex data to the unmanaged array
meshData.verticeCount = 1;