#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.