2012-03-23 196 views
4

在C#,我所定义的结构:转换结构手柄从托管到非托管C++/CLI

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

这是我能想到的不过关过程中,我得到这个错误:

Error 2 error C2275: 'MyObject' : illegal use of this type as an expression

是转换是正确的托管对象变为非托管对象?如果是这样,那么我怎样才能正确地确定Marshal::PtrToStructure?如果不是,我该怎么办?

+0

除非您定义名为'LPWSTR'的别名(或实际类型),否则您的C#将不会编译。 – svick 2012-03-23 16:14:37

+0

这是我的错误。我只是更新了它 – olidev 2012-03-23 16:16:04

+0

像他的回答中提到的@Botz一样,这里没有非托管类型。你想做什么? – 2012-03-23 16:18:57

回答

2

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

另外,您需要定义一个非托管类,因为MyObject是一个托管类型。假设你已经这样做了,你可以做这样的(只是转换这从C#示例):

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

然后,您有一个指针数据,这些数据可以memcpy或任何到您的原生结构。

但是MyObject是和将保持托管类型。如果你想要一个真正的非托管类型,你必须定义一个与托管结构相匹配的类型。

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

+0

我刚刚更新了我的问题,其中也包括C#中的对象,您可以看到我在C++中定义了相同的问题。你是对的,我复制托管对象configObject到pnt。但是我怎样才能从那个pnt创建一个非托管的ConfigObject呢?提前致谢。 – olidev 2012-03-23 16:10:54

+0

这些类定义都是管理的。你为什么不在C++程序集中只定义类**,并使用C#中的类?我的意思是你已经引用了图书馆。然后你会使用同一个班级。 – Botz3000 2012-03-23 16:18:37

+0

我对这个主题没有经验,从C#发送一个结构到C++。所以你的意思是我需要先用C++来构造它,然后再使用C#。 C++中的结构定义应该是什么?你能给我建议吗?在此先感谢 – olidev 2012-03-25 19:51:14

1

你大概的意思是:

struct MyUnmanagedStruct { 
    LPWSTR var1, var2; 
}; 

然后你可以使用Marshal.StructureToPtr通过Botz3000的建议。否则,C#的

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

和C++/CLI的

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

是完全等价的,假设your're你使用两边的相同System.String

+0

谢谢。因为我问了另一个问题:http://stackoverflow.com/questions/9651585/how-to-set-an-object-into-c-from-c-sharp,他们建议使用LPWSTR。对于你的其他解决方案,我需要将String ^转换为C++中的字符串,对吧? – olidev 2012-03-25 19:49:33

+0

嗯,不,或者是...因为我不确定你现在在做什么。在另一个线程中,您询问如何使.NET对象可用于native C++。是的,你得到的答案是一种可能的方式,尽管不是最优雅的,也不是最安全的。从你在这里发布的内容可以看出,当你试图做一些奇怪的事情时:将未调整的字符串存储在托管值类型“public value struct MyObject”中... – 2012-03-28 15:20:20