【问题标题】:Using a managed c# dll inside an unmanaged c++ dll在非托管 c++ dll 中使用托管 c# dll
【发布时间】:2014-11-26 01:09:45
【问题描述】:

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

一些上下文: 我有一个导入类型库 (.tlb) 的 c++ .dll,在其中一个 c++ 函数中,我实例化了一个指向 c#.dll 中函数的指针。然后,使用该指针,我可以在 c++ 中调用 c# 函数。我想知道 c++ .dll 如何知道 c# .dll 在哪里?此外,有没有更好的方法来进行这种类型的编码?

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

【问题讨论】:

    标签: c# c++ dll typelib


    【解决方案1】:

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

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

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

    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 Studios 提供的 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 Studios 中包含的 tlbexp 命令生成。该命令的示例使用如下:

    tlbexp NameofC#DLL.dll

    如果您不指定路径,它将默认为以下路径:

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

    有几个地方你可以把它搞砸,C# DLL 调用会失败。

    问候,

    海苔设计

    【讨论】:

      【解决方案2】:

      也许我遗漏了一些东西,但您可以创建一个自定义 CLR host 并从 C# 调用一个不带指针的方法。签出ICLRRuntimeHost::ExecuteInDefaultAppDomain

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-14
        • 1970-01-01
        • 2013-01-07
        • 1970-01-01
        • 2011-04-29
        相关资源
        最近更新 更多