у меня есть Приложение C ++ для Windows, разработанное с помощью RAD Studio (C ++ Builder) XE4. Он имеет несколько плагинов, которые являются DLL (всегда пишутся с RAD Studio), которые динамически загружаются с эта техника.
Теперь в одном из этих плагинов мне нужны возможности отражения. Хотя кажется, что я не могу достичь их с помощью C ++ (требуется отражение в сторонней COM-DLL, которую я не могу изменить), я решил переписать это плагин в C # (который имеет мощные способности отражения), создавая тем самым .Чистая сборка.
Я знаю, что должен выставить сборку через COM, но не могу (мы не хотим менять способ, которым основное приложение загружает все библиотеки DLL).
Моя цель состоит в том, чтобы динамически загружать сборку .NET и вызывать ее функции (например, здесь мы называем SetParam
функция) с чем-то вроде следующего, как я делаю с другими плагинами.
//load DLL
HINSTANCE handleDll = LoadLibraryW("C:/Path/to/the/assembly.dll");
//get reference to the function
void* ptr = GetProcAddress(handleDll, "_SetParam");
ptr_SetParam ptrFunc = reinterpret_cast<ptr_SetParam>(ptr);
//invoke function
int result = (*ptrFunc)(String("mykey").c_str(), String("myvalue").c_str());
где ptr_SetParam
определяется как
typedef int(*ptr_SetParam)(const wchar_t*, const wchar_t*);
Есть ли способ?
Благодаря комментарию @ HansPassant я нашел способ.
Я создал следующие проекты Visual Studio.
MyDllCore .Проект сборки NET, написанный на C # или любом другом языке .NET. Здесь у меня есть управляемый класс, подобный следующему, где реализована реальная логика сборки.
using System;
using System.Collections.Generic;
//more usings...
namespace MyNamespace
{
public class HostDllB1
{
private Dictionary<string, string> Parameters = new Dictionary<string, string>();
public HostDllB1()
{
}
public int SetParam(string name, string value)
{
Parameters[name] = value;
return 1;
}
}
}
MyDllBridge Проект DLL, написанный на C ++ / CLI, с /clr
опция компилятора. Это просто «мостовой» проект, он зависит от проекта MyDllCore и имеет только один файл .cpp o .h, как показано ниже, где я сопоставляю методы из программы, загружающей DLL, с методами в сборке .NET ,
using namespace std;
using namespace System;
using namespace MyNamespace;
//more namespaces...
#pragma once
#define __dll__
#include <string.h>
#include <wchar.h>
#include "vcclr.h"//more includes...
//References to the managed objects (mainly written in C#)
ref class ManagedGlobals
{
public:
static MyManagedClass^ m = gcnew MyManagedClass;
};
int SetParam(const wchar_t* name, const wchar_t* value)
{
return ManagedGlobals::m->SetParam(gcnew String(name), gcnew String(value));
}
Наконец у меня есть Программа C ++ Builder который загружает MyDllBridge.dll и использует его методы, вызывая их, как показано ниже.
//load DLL
HINSTANCE handleDll = LoadLibraryW("C:/Path/to/the/MyDllBridge.dll");
//get reference to the function
void* ptr = GetProcAddress(handleDll, "SetParam");
ptr_SetParam ptrFunc = reinterpret_cast<ptr_SetParam>(ptr);
//invoke function
int result = (*ptrFunc)(String("mykey").c_str(), String("myvalue").c_str());