Использование управляемой библиотеки c # dll внутри неуправляемой библиотеки c dll

#c# #c #dll #typelib

#c# #c #dll #typelib

Вопрос:

Как работает неуправляемый c .dll знает, где находится управляемая c # .dll?

Некоторый контекст: у меня есть c .dll, которая импортирует библиотеку типов (.tlb) и внутри одной из функций c , я создаю экземпляр указателя на функции внутри c # .dll. Затем, используя этот указатель, я могу вызывать функции c # в c . Я хотел бы знать, как c .dll знает, где находится c # .dll? Кроме того, есть ли лучший способ выполнить этот тип кодирования?

Должен ли файл .tlb находиться в том же каталоге, что и c # .dll?

Ответ №1:

Один из способов достижения вышеуказанного — зарегистрировать файл C # dll в реестре Microsoft Windows с помощью команды regasm. Эта команда EXE включена в дистрибутивы Visual Studios. Ниже приведен пример использования команды:

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

После того, как вы зарегистрируете ее в реестре, вам нужно будет установить ее в глобальный кэш сборок (GAC) с помощью команды gacutil. Это также входит в дистрибутивы 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 #. Это число может быть сгенерировано случайным образом с помощью средства создания GUID, поставляемого с Visual Studios в разделе «Меню инструментов» и опции «Создать 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**>(amp;CSharpInterface));

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

    //Close interface
    CoUninitialize();

    //Return result
    return resu<
}
  

Требуемый файл TLB во время компиляции может быть сгенерирован с помощью команды tlbexp, также входящей в состав Visual Studios.Ниже приведен пример использования команды:

tlbexp NameofC#DLL.dll

Если вы не укажете путь, по умолчанию будет указан следующий путь:

C:Program FilesMicrosoft Visual Studio 9.0VC

В нескольких местах вы можете это испортить, и вызов C # DLL завершится ошибкой.

С уважением,

SeaMossDesign

Ответ №2:

Возможно, я что-то упускаю, но вы можете создать пользовательский узел CLR и вызвать метод из C # без указателя. Проверьте ICLRRuntimeHost::ExecuteInDefaultAppDomain.