将C#struct传递给C ++ / CLI for C ++包装器

时间:2012-03-06 07:51:39

标签: c# c++ interop c++-cli

昨天发布问题之后我认为我已经解决了这个问题,但我仍然遇到问题,我有一个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 ++结构指针?在这种情况下,我应该传递什么,我应该如何编组呢?

1 个答案:

答案 0 :(得分:1)

您没有获得序列化过程:

// !! 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之前,您可能并不关心那里的内容。

顺便说一句,你的命名约定有点糟糕。你应该用C ++中的大写字母开始变量名。