在 C++ 非托管应用程序中使用 C# 托管应用程序类

Posted

技术标签:

【中文标题】在 C++ 非托管应用程序中使用 C# 托管应用程序类【英文标题】:Use C# managed app class in C++ unmanaged app 【发布时间】:2014-03-24 07:43:47 【问题描述】:

我有一个用 C# 编写的类的项目,我用它来序列化一些数据。

 [XmlType("CPersoane")]
 public class CPersoana
 
        public CPersoana()  

        [XmlElement("name")]
        public string Name  get; set; 

        [XmlElement("profession")]
        public string Profession get; set; 

        [XmlAttribute("age")]
        public int Age get; set; 

        //...

我在同一个解决方案中还有另一个项目,它编写了 C++ MFC(不支持 CLR),带有一个带有 3 个文本框的对话框。

如何从 C++ 访问“CPersoana”类,以便在文本框中使用“姓名”、“职业”和“年龄”?

任何帮助将不胜感激!

【问题讨论】:

我认为编写 COM(组件对象模型)是一种选择。但并不容易。 我试过了,但没有任何运气。 【参考方案1】:

首先,您的 c# 项目需要是一个 DLL(输出类型 = 类库)。

其次,您无法在非托管 C++ 中访问 c​​# 代码,您的 C++ 项目至少需要一个使用 /CLR 编译的源文件,您可以在其中访问您的 c# 类。

在那个源文件中,你可以编写如下代码

#using "MyCSharpProject.DLL"
using namespace MyCSharpNamespace;
...
gcroot<CPersoana^> pPersona = gcnew CPersoana();
CString sFileName = <path to file>;
pPersona->LoadFromFile(gcnew System::String(sFileName));
// LoadFromFile would be a member function in the CPersoana class
// like bool LoadFromFile(string sFileName)
CString sName(pPersona->Name->ToString();
...

【讨论】:

【参考方案2】:

编写 COM 应该不难:

namespace CPersoanaNameSpace

   [Guid("8578CEB3-6C04-4FC2-BB80-FB371A9F")]
   [ComVisible(true)]
   public interface ICPersoanaCOM
   

      [DispId(1)]
      void Name(out string name);

      [DispId(2)]
      void Profession(out string profession);

      [DispId(3)]
      void Age(out int age);
    
    

实现接口

   [ComVisible(true)]
   [Guid("6BE742E0-CDEC-493A-B755-D5Crtr5w6A545"),
   public class CPersoana: ICPersoanaCOM
   
//...
   

然后在 C++ 中使用它:

//Import tlb
#import "path to tlb\Persoana.tlb"  named_guids raw_interfaces_only
using namespace System;

int main(array<System::String ^> ^args)


   CoInitialize(NULL);   //Initialize all COM Components


   CPersoanaNameSpace::CPersoanaCOMPtr objPtr;

  HRESULT hRes =  objPtr.CreateInstance(CPersoanaNameSpace::CLSID_CPersoana);
  if (hRes == S_OK)
  
      BSTR LocName;
      objPtr->Name(&LocName);
      


【讨论】:

您的 C++ 代码是 Visual C++,因此无论如何它都需要 CLR。这意味着做 COM 没有意义 - 请参阅接受的答案。

以上是关于在 C++ 非托管应用程序中使用 C# 托管应用程序类的主要内容,如果未能解决你的问题,请参考以下文章

从非托管 c++ 调用 C# 函数(通过托管包装器)

在 C# 应用程序退出时清理非托管 C++ 线程

非托管 C# 与 C++ [关闭]

将回调参数从 C# 传递到非托管 C++

从 C# 调用非托管 C++ VS 6.0 MFC dll

PInvokeStackImbalance C# 调用非托管 C++ 函数