在非托管c ++ dll中使用托管c#dll

时间:2011-05-22 04:18:24

标签: c# c++ dll typelib

非托管c ++ .dll如何知道托管c#.dll的位置在哪里?

某些背景: 我有一个c ++ .dll导入一个类型库(.tlb)并且在一个c ++函数中,我实例化了一个指向c#.dll中函数的指针。然后,使用该指针,我可以在c ++中调用c#函数。我想知道c ++ .dll是如何知道c#.dll的位置的?此外,有更好的方法来进行这种编码吗?

.tlb是否需要与c#.dll在同一目录中?

2 个答案:

答案 0 :(得分:4)

完成上述操作的一种方法是使用regasm命令向Microsoft Windows注册表注册C#dll文件。此命令EXE包含在Visual Studios的发行版中。该命令的示例使用如下:

regasm NameofC#DLL.dll /tlb:NameofC#DLL.tlb

在注册表中注册后,您需要使用gacutil命令将其安装到全局程序集缓存(GAC)。这也包含在Visual Studios的发行版中。该命令的示例使用如下:

gacutil / i NameofC#DLL.dll

完成这些步骤后,您的C ++代码将能够找到C#dll,假设您的DLL文件的构造类似于以下内容:

[C#]

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace MyNameSpace
{
    /// <summary>
    /// Interface for C++ DLL. This exposes the functions used inside the dll
    /// Make sure the return types, function names, and argument types match the class
    /// </summary>
    [ComVisible(true)]
    [Guid("CBA208F2-E43B-4958-97C7-C24EA5A213DE")]
    public interface IMyClass
    {
        int Function1();
        int Function2();
    }

    [ClassInterface(ClassInterfaceType.None)]
    [Guid("579091E6-83A1-4aa5-89A7-F432AB2A57E3")]
    [ComVisible(true)]
    public class MyClass : IMyClass
    {
        public MyClass()
        {
            //Constructor
        }

       public int Function1()
        {
            //Do something in C#

            return an integer;
        }

        public int Function2()
        {
            //Do something else in C#

            return an integer;
        }
    }//End Class MyClass
}//End namespace MyNameSpace

在任何地方,您都会看到正在使用的GUID,这是一个随机生成的全局标识符,用于标识您的C#代码。可以使用“工具菜单”下的Visual Studio随附的GUID创建工具和“创建GUID”选项随机生成此编号。选择注册表格式,然后按“新GUID”。然后按下复制并将其粘贴到GUID所需的位置(删除括号!)

[C ++]

#include <windows.h>
#include "stdafx.h"
#include <cstdlib>
#pragma warning (disable: 4278)
#import <mscorlib.tlb> raw_interfaces_only
#include <stdio.h>
//This path needs to be valid at compile time. The file does not need to be there in runtime when using the DLL after compile.
#import "C:\\...\\NameofC#DLL.tlb" no_namespace named_guids

extern "C" _declspec(dllexport) int _Function1()
{   
        int result = 0;
    IMyClass *CSharpInterface = NULL;

    //Open interface to C#
    CoInitialize(NULL);
    HRESULT hr = CoCreateInstance(CLSID_MyClass, NULL, CLSCTX_INPROC_SERVER,
                                  IID_IMyClass, reinterpret_cast<void**>(&CSharpInterface));

    //Call Function1 C# method
    result = CSharpInterface->Function1();

    //Close interface
    CoUninitialize();

    //Return result
    return result;
}

编译时所需的TLB文件可以使用visual studio中包含的tlbexp命令生成。该命令的示例使用如下:

tlbexp NameofC#DLL.dll

如果您未指定路径,则默认为以下路径:

C:\ Program Files \ Microsoft Visual Studio 9.0 \ VC

有几个地方可以解决这个问题,C#DLL调用将会失败。

此致

SeaMossDesign

答案 1 :(得分:1)

也许我错过了一些东西,但你可以创建一个自定义CLR host并从C#调用一个没有指针的方法。检查ICLRRuntimeHost::ExecuteInDefaultAppDomain