Использование управляемого c # dll внутри неуправляемого dll c ++ - PullRequest
4 голосов
/ 22 мая 2011

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

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

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

Ответы [ 2 ]

4 голосов
/ 25 мая 2011

Одним из способов выполнения вышеизложенного является регистрация файла 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**>(&CSharpInterface));

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

    //Close interface
    CoUninitialize();

    //Return result
    return result;
}

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

tlbexp NameofC # DLL.dll

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

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

Есть несколько мест, где вы можете испортить это, и вызов C # DLL завершится неудачей.

С уважением,

SeaMossDesign

1 голос
/ 22 мая 2011

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

...