将C#结构传递给C++包装器的C++/CLI

本文关键字:C++ 包装 CLI 结构 | 更新日期: 2023-09-27 18:26:43

昨天发布了一个问题后,我以为我已经解决了这个问题,但我仍然有问题,我有一个C++类的C++/CLI包装器,C++类的一些函数将recv的缓冲区作为参数,数据包结构被定义为C++结构,这就是参数。

在C#中,我使用structlayout复制了这些C++结构,这样我在C#中就有了等效的结构,它们在内存中的布局与我的C++结构相同。在我的C++/CLI代码中,我尝试了以下

UINT GetValues(value class^ JPVals) // value class, as C# structs are value types
{
IntPtr ptr;
Marshal::StructureToPtr(JPVals,ptr,false);
return m_pComms->GetValues(ptr,0); // m_pComms is a wrapped unmanaged class 
    //GetValues takes a pointer to a C++ struct
}

我得到的错误是无法将参数1从"System::IntPtr"转换为"SJPVal*",为什么不可能将Marshall从值类转换为C++结构指针?在这种情况下,我应该传递什么?我应该如何组织它?

将C#结构传递给C++包装器的C++/CLI

您没有得到序列化过程:

// !! Note the % !!
UINT GetValues(value class% JPVals) // value class, as C# structs are value types 
{ 
    // Allocate a buffer for serialization, pointer to NULL otherwise
    IntPtr ptr = Marshal::AllocHGlobal(Marshal::SizeOf(JPVals));
    try {
        // Serialize the managed object to "static" memory (not managed by the GC)
        Marshal::StructureToPtr(JPVals, ptr, false); 
        // Pass it to unmanaged code that will modify it.
        auto ret = m_pComms->GetValues(reinterpret_cast<SJPVal*>(ptr.ToPointer()), 0);
        // Copies the modifications back
        Marshal::PtrToStructure(ptr, JPVals);
        // Free resources
        Marshal::FreeHGlobal(ptr);
        return ret;
    } catch (...) {
        // Make sure we free the memory
        Marshal.FreeHGlobal(ptr);
        throw; 
    }
} 

编辑:显示了如何复制回值。

当您使用C#struct时,您需要通过引用传递它,以确保更改被复制回来。或者,该代码将与C#class一样工作。现在,第一步(StructureToPtr)可能没有用,因为在调用GetValues之前,您可能不关心里面有什么。

顺便说一下,你的命名约定有点糟糕。您应该NOT在C++中以大写字母开头变量名。