如何构造一个结构数组的指针

时间:2010-01-14 04:04:36

标签: c# arrays struct pointers marshalling

我正在调用C ++中的函数,它返回一个指向struct数组的指针,因为我是这个操作/实现的新手,所以我遇到了问题。

我的C ++代码:

// My C++ Structs

typedef struct _MainData {

    double      dCount;
    DataS1          *DS1;
    int     iCount1;
    DataS2          *DS2;
    int     iCount2;
}MainData;

typedef struct _DataS1 {

    unsigned int    uiCount1;   
    unsigned int    uiCount2;   
    int     iCount;
    void        *pA;    
    void        *pB;    

} DataS1;

typedef struct _DataS2 {

    unsigned int    uiCount1;   
    unsigned int    uiCount2;               
    unsigned int    uiCount3;               
    unsigned int    uiCount4;           
    double      dCount; 
    int     iCount1;                    
    char        strLbl[64];
} DataS2;

// My C++ Function

MainData* GetData(const int ID)
{

        MainData* mData;
        int iLength = Get_Count();
    mData = new MainData[iLength];
        for(int x = 0;x < VarCounter; x++)
        {
            // Codes here assign data to mData[x]
        }
        return mData;
}

问题: 如何将C ++函数GetData调用到C#?

我目前在C#中的代码是:

[DllImport(".\\sdata.dll")]
[return: MarshalAs(UnmanagedType.LPArray)]
private static unsafe extern MainData[] GetData(int ID);


// The struct MainData in my C# side is already "Marshalled"...

//My function call is here:
MainData[] SmpMapData = GetData(ID);

当我编译它时,有一个例外: “无法封送'返回值':托管/非托管类型组合无效。”

抱歉编码不好......请帮忙...

2 个答案:

答案 0 :(得分:2)

  • 首先,您需要记住,返回值的MarshalAs(显式或隐式)实质上意味着“将本机结构内容复制到托管结构中”。
  • 其次,由于CLR封送程序只复制数据,如果你没有释放你在C ++函数中分配的内存,你就会有内存泄漏需要管理。
  • 第三,这个错误主要是由于CLR封送程序无法知道本机代码返回的数组的长度这一事实,因为你基本上都返回了一个内存指针并没有长度。

如果你想保持这些内存结构不变,我强烈建议你研究一下C ++ / CLI。您将能够将这些复杂类型包装到混合的本机/托管类中,从而避免复制数据。这将帮助您将本地和托管代码之间的数据编组保持在最低限度。

如果您仍想使用C#而不使用C ++ / CLI,则必须编写一些更智能的代码来解析本机代码返回到托管数据的数据。您可以查看Custom Marshaling

答案 1 :(得分:0)

我没有看到.NET运行时如何知道在MainData中分配了多少GetData(...)

重构您的C ++代码以使用数组来填充或返回单个MainData