简体   繁体   English

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

[英]Using a managed c# dll inside an unmanaged c++ dll

How does an unmanaged c++ .dll know where the location of a managed c# .dll is? 非托管c ++ .dll如何知道托管c#.dll的位置?

Some context: I have a c++ .dll that imports a type library (.tlb) and inside one of the c++ functions, I instantiate a pointer to the functions inside the c# .dll. 一些上下文:我有一个c ++ .dll导入一个类型库(.tlb),在一个c ++函数中,我实例化了一个指向c#.dll里面函数的指针。 Then, using that pointer, I can call the c# functions in c++. 然后,使用该指针,我可以在c ++中调用c#函数。 I would like to know how c++ .dll know where the c# .dll is? 我想知道c ++ .dll是如何知道c#.dll的位置的? Further, is there a better way to do this type of coding? 此外,还有更好的方法来进行这种编码吗?

Does the .tlb need to be in the same directory as the c# .dll? .tlb是否需要与c#.dll位于同一目录中?

One way to accomplishing the above is to register the C# dll file with the Microsoft Windows Registry using the regasm command. 完成上述操作的一种方法是使用regasm命令向Microsoft Windows注册表注册C#dll文件。 This command EXE is included with distributions of Visual Studios. 此命令EXE包含在Visual Studios的发行版中。 An example use of the command follows: 该命令的示例使用如下:

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

Once you have registered it in the registry you will need to install it to the global assembly cache (GAC) using the gacutil command. 在注册表中注册后,需要使用gacutil命令将其安装到全局程序集缓存(GAC)。 This is also included with distributions of Visual Studios. 这也包含在Visual Studios的发行版中。 An example use of the command follows: 该命令的示例使用如下:

gacutil /i NameofC#DLL.dll gacutil / i NameofC#DLL.dll

Once these steps are completed your C++ code will be able to find the C# dll assuming your DLL files are constructed similar to the following: 完成这些步骤后,您的C ++代码将能够找到C#dll,假设您的DLL文件的构造类似于以下内容:

[C#] [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

Everywhere you see a GUID being used, that is a randomly generated global identifier used to identify your C# code. 在任何地方,您都会看到正在使用的GUID,这是一个随机生成的全局标识符,用于标识您的C#代码。 This number can be randomly generated using the GUID creation tool provided with Visual Studios under the "Tool menu" and the "Create GUID" option. 可以使用“工具菜单”下的Visual Studio随附的GUID创建工具和“创建GUID”选项随机生成此编号。 Select Registry format and press "New GUID". 选择注册表格式,然后按“新GUID”。 Then just press copy and paste it where the GUID needs to be (Remove the brackets!) 然后按下复制并将其粘贴到GUID所需的位置(删除括号!)

[C++] [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;
}

The required TLB file at compile time can be generated using the tlbexp command also included with visual studios.An example use of the command follows: 编译时所需的TLB文件可以使用visual studio中包含的tlbexp命令生成。该命令的示例使用如下:

tlbexp NameofC#DLL.dll tlbexp NameofC#DLL.dll

If you do not specify a path it will default to the following path: 如果未指定路径,则默认为以下路径:

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

There a several places you can mess this up and the C# DLL call will fail. 有几个地方你可以搞砸了,C#DLL调用将失败。

Regards, 问候,

SeaMossDesign SeaMossDesign

Maybe I'm missing something, but you can create a custom CLR host and invoke a method from C# without pointer. 也许我错过了一些东西,但你可以创建一个自定义CLR主机并从C#调用一个没有指针的方法。 Check ICLRRuntimeHost::ExecuteInDefaultAppDomain out. 检查ICLRRuntimeHost :: ExecuteInDefaultAppDomain

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM