在非托管C ++程序中实现C#DLL COM文件

这是我的另一个问题,也引用了这个问题作为参考: 如何从Un-managed C ++调用托管C ++方法

我已经成功创建了一个C#COM文件。 现在我需要一个关于如何在非托管C ++中实现它的简单解释。

我遵循这个例子,但c ++部分很弱。 http://www.codeproject.com/Articles/7859/Building-COM-Objects-in-C

这是我的COM文件

using System; using System.Runtime.InteropServices; using System.Collections.Generic; using System.Linq; using System.Text; namespace cSharpRiJHarn { [Guid("ED1483A3-000A-41f5-B1BC-5235F5897872")] public interface DBCOM_Interface { [DispId(1)] String encrypt(string s); [DispId(2)] String decrpyt(string s); } [Guid("A6BCEC1D-B60C-4c97-B9AD-1FE72642A9F8"), InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] public interface DBCOM_Events { } [Guid("7C13A8C6-4230-445f-8C77-0CA5EDECDCB5"), ClassInterface(ClassInterfaceType.None), ComSourceInterfaces(typeof(DBCOM_Events))] public class RijndaelLink : DBCOM_Interface { public String encrypt(String s) { return Rijndael.EncryptString(s); } public String decrpyt(String s) { return Rijndael.DecryptString(s); } } } 

我只想要一个非常基本的例子来使用非托管代码。 请在你的答案中包括:

  • 我是否需要包含项目或仅包含COM的源文件
  • 我是否需要添加参考
  • 传递字符串并使用cout打印出来的一个非常基本的例子。

谢谢你的帮助!

您需要做的第一件事是在.NET中正确定义COM对象,供非托管世界(C ++或其他)使用。 这是一个不错的定义:

 namespace cSharpRiJHarn { [Guid("ED1483A3-000A-41f5-B1BC-5235F5897872")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [ComVisible(true)] public interface IRijndaelLink { string encrypt(string s); string decrypt(string s); } [Guid("7C13A8C6-4230-445f-8C77-0CA5EDECDCB5")] [ComVisible(true)] public class RijndaelLink : IRijndaelLink { public string encrypt(string s) { return Rijndael.EncryptString(s); } public string decrypt(string s) { return Rijndael.DecryptString(s); } } } 

接下来,您需要使用RegAsm工具为COM注册此.NET程序集。 我建议你用它构建一个类型库(.TLB) ,就像这样(我想你为X86构建了整个东西,而不是X64):

 c:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe YourAssembly.dll /tlb:YourAssembly.tlb /codebase 

请适应您的实际路径。 还要检查代码库arg,因为在生产中可能不需要它。

这将构建一个包含接口和类的.TLB文件。 它的工作原理是因为我们添加了ComVisible属性。 您还会注意到我没有定义Dispatch或Dual接口,因为在此示例中,我不需要COM Automation (VB,VBA)或任何脚本语言(VBScript,JScript)支持,只有IUnknown接口更容易使用在普通的C / C ++中比IDispatch接口。

现在,有一种简单的方法可以使用Microsoft特定的C ++扩展在非托管c ++世界中导入它: #import Directive ,类似于.NET中的Add References。 以下是使用COM对象的示例控制台应用程序:

 #include "stdafx.h" #import "c:\MyPathToTheTlb\YourAssembly.tlb" // import the COM TLB using namespace YourAssembly; int _tmain(int argc, _TCHAR* argv[]) { CoInitialize(NULL); // needed to enter COM space IRijndaelLinkPtr ptr(__uuidof(RijndaelLink)); // create the COM Object with the desired interface _bstr_t s = ptr->encrypt("hello"); // call the function printf("%S", (LPWSTR)s); // for example CoUninitialize(); return 0; } 

你会注意到#import指令也创建了很酷的包装器(_bstr_t,因为.NET String将在这里导出为Automation BSTR,即使是IUnknown接口)也可以用于字符串处理,所以这并不是什么大问题。

这不是所有这一切都可以工作的唯一方式,但那是恕我直言最简单的方法之一。