首页 文章

将C#struct传递给C / CLI以获取C包装器

提问于
浏览
1

在昨天发布问题之后,我认为我已经解决了这个问题,但我仍然遇到问题,我有一个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 回答

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

    EDIT: 显示了如何复制该值 .

    当您使用C# struct 时,您需要通过引用传递它以确保复制更改 . 或者,代码与C# class 的工作方式相同 . 现在,第一步( StructureToPtr )可能没用,因为你可能在关注 GetValues 之前并不关心那里的内容 .

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

相关问题