编组结构体数组指针的方法

发布于 2024-08-18 04:26:10 字数 1466 浏览 4 评论 0原文

我正在从 C++ 调用函数,该函数返回一个指向结构数组的指针,但我遇到了问题,因为我是这个操作/实现的新手。

我的 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# 中调用 C++ 函数 GetData?

我当前的 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);

当我编译它时,出现异常: “无法封送‘返回值’:托管/非托管类型组合无效。”

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

I'm calling functions from C++ that returns a pointer to an array of struct and I'm having problems since I'm new to this operation/implementation.

My C++ codes:

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

Question:
How can I call the C++ function GetData to C#?

My current codes in C# are:

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

When I compiled it, there's an exception:
"Cannot marshal 'return value': Invalid managed/unmanaged type combination."

Sorry for the poor coding... Please help...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

  • 首先,您需要记住返回值的 MarshalAs(显式或隐式)本质上意味着“将本机结构内容复制到托管结构中”。
  • 其次,由于 CLR 封送拆收器仅复制数据,因此如果不释放在 C++ 函数中分配的内存,则需要管理内存泄漏。
  • 第三,此错误主要是由于 CLR 封送拆收器无法知道本机代码返回的数组的长度,因为您基本上返回的是内存指针而不是长度。

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

如果您仍然想使用 C# 而不是 C++/CLI,则必须编写一段更智能的代码来将本机代码返回的数据解组为托管数据。您可以查看自定义封送处理

  • First, you need to remember that MarshalAs (explicit or implicit) for the return value essentially means "copy native structures content into managed structures".
  • Second, since the CLR marshaler only copies the data, if you do not free the memory you're allocated in the C++ function, you've got a memory leak to manage.
  • Third, this error is mainly due to the fact that the CLR marshaler has no way of knowing the length of the array returned by the native code, since you're basically returning a memory pointer and no length.

If you want to keep these memory structures as-is, I strongly suggest you to look into C++/CLI. You'll be able to wrap those complex types into mixed native/managed classes that will avoid you to copy the data around. This will help you keep the data marshaling to the bare minimum between native and managed code.

If you still want to use C# and no C++/CLI, you'll have to write a somehow smarter piece of code to unmarshal the data returned by the native code into managed data. You can look into Custom Marshaling for that.

邮友 2024-08-25 04:26:10

我不明白 .NET 运行时如何知道在 GetData(...) 中分配了多少 MainData

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

I don't see how the .NET runtime could possibly know how many MainData are allocated in GetData(...).

Refactor your C++ code to consume an array to populate or return single MainDatas.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文