将结构句柄从托管转换为非托管C++/CLI

convert struct handle from managed into unmanaged C++/CLI

本文关键字:C++ CLI 转换 结构 句柄      更新时间:2023-10-16

在C#中,我定义了一个结构:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct MyObject
{
   [MarshalAs(UnmanagedType.LPWStr)]
   public string var1;    
   [MarshalAs(UnmanagedType.LPWStr)]
   public string  var2;    
};

我在C++中有这个结构:

public value struct MyObject
{
    LPWSTR var1;    
    LPWSTR var2;    
};

在C++的方法中,它是一个从C#调用的公共类:

TestingObject(MyObject^ configObject)
{
   // convert configObject from managed to unmanaged.
}

对象调试正确,我可以看到两个字符串var1和var2。但是,现在的问题是,我需要将对象configObject封送到非托管对象中。

我想到的是做这样的事情:

TestingObject(MyObject^ configObject)
{
   // convert configObject from managed to unmanaged.
   MyObject unmanagedObj = (MyObject)Marshal::PtrToStructure(configObject, MyObject);  
}

这就是我所能想到的,但当然,我得到了这个错误:

错误2错误C2275:"MyObject":将此类型非法用作表达式

将托管对象转换为非托管对象是否正确?如果是,我如何才能正确地使用Marshal::PtrToStructure?如果没有,我该怎么做?

Marshal::PtrToStructure的作用与您想要的相反,它将非托管指针转换为托管对象。您需要Marshal::StructureToPtr

此外,您还需要定义一个非托管类,因为MyObject是一个托管类型。假设你已经做到了,你可以这样做(只是从C#样本转换过来):

IntPtr pnt = Marshal::AllocHGlobal(Marshal::SizeOf(configObject)); 
Marshal.StructureToPtr(configObject, pnt, false);

然后,您就有了一个指向数据的指针,您可以将其memcpy或其他任何东西放入您的本机结构中。

但是MyObject现在是并且将继续是托管类型。如果您想要一个真正的非托管类型,则必须定义一个与托管结构匹配的类型。

只是想知道,为什么在托管结构中使用非托管LPWSTR?

您的意思可能是:

struct MyUnmanagedStruct {
    LPWSTR var1, var2;
};

然后您可以按照Botz3000的建议使用Marshal.StructureToPtr。否则,C#的

public struct MyObject {
   public String var1;
   public String var2;
}

和C++/CLI的

public struct value MyObject {
   public String^ var1;
   public String^ var2;
}

是完全等效的,假设您在两侧使用相同的System.String