在非托管c++程序中实现一个c# DLL COM文件



这是我的另一个问题,也导致了这个参考:如何从非托管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:WindowsMicrosoft.NETFrameworkv4.0.30319RegAsm.exe YourAssembly.dll /tlb:YourAssembly.tlb /codebase

请适应您的实际路径。还要检查cocode base参数,因为在生产环境中可能不需要它。

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

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

#include "stdafx.h"
#import  "c:MyPathToTheTlbYourAssembly.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将在这里导出为自动化BSTR,即使对于IUnknown接口也是如此),所以这没什么大不了的。

这不是唯一的方法,但我认为这是最简单的方法之一。

最新更新