【问题标题】:convert struct handle from managed into unmanaged C++/CLI将结构句柄从托管转换为非托管 C++/CLI
【发布时间】:2012-04-08 02:38:58
【问题描述】:

在 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?如果没有,我该怎么办?

【问题讨论】:

  • 你的 C# 不会编译,除非你定义了别名(或实际类型)称为 LPWSTR
  • 这是我的错误。我刚刚更新了它
  • 就像@Botz 在他的回答中提到的那样,这里没有非托管类型。你想做什么?

标签: c++ c++-cli unmanaged


【解决方案1】:

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

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

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

然后你有一个指向数据的指针,你可以将它memcpy 或其他任何东西放入你的原生结构中。

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

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

【讨论】:

  • 我刚刚更新了我的问题,其中还包括 C# 中的对象,您可以看到我在 C++ 中定义了相同的对象。你是对的,我将托管对象 configObject 复制到 pnt。但是我怎样才能从那个 pnt 创建一个非托管的 ConfigObject 呢?提前致谢。
  • 这些类定义都是托管的。为什么不在 C++ 程序集中定义类 only 并在 C# 中使用它?我的意思是你已经引用了图书馆。那么你将使用相同的类。
  • 我对这个主题没有经验,无法将结构从 C# 发送到 C++。所以你的意思是我需要先在 C++ 中构造它,然后从 C# 中使用。 C++ 中的结构定义应该是什么?你能建议我吗?提前致谢
  • 这取决于你想用它做什么。为什么它需要不受管理?您可以使用 C++ 中已有的结构,但不要使用 LPWSTR,而是使用 String^。这样,您就可以在 C# 和 C++ 中使用它。
  • 好吧。我只是尝试按照下面 Paul 的建议更新 C# 和 C++ 中的结构。 var1 将是字符串^。为了打印它,我必须这样: printf((const char*)(Marshal::StringToHGlobalAnsi(myObject->var1)).ToPointer());但我在那条线上遇到了一个例外
【解决方案2】:

你的意思可能是:

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

【讨论】:

  • 谢谢。因为我问了另一个问题:stackoverflow.com/questions/9651585/…,他们建议使用 LPWSTR。对于您的其他解决方案,我需要将 String^ 转换为 C++ 中的字符串,对吗?
  • 嗯,不是或是...因为我不确定您现在在做什么。在另一个线程中,您询问了如何使 .NET 对象可用于本机 c++。是的,你得到的答案是一种可能的方法,虽然不是最优雅的,也不是最安全的。从您在此处发布的内容来看,您似乎在尝试做一些奇怪的事情:将未管理的字符串存储在托管值类型 public value struct MyObject...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 2011-10-07
  • 2011-02-27
  • 1970-01-01
相关资源
最近更新 更多