在 C++Builder 应用程序中动态加载 C# .NET 程序集
Dynamically load a C# .NET assembly in a C++Builder application
我有一个使用 RAD Studio (C++Builder) XE4 开发的 C++ Windows 应用程序。它有一些插件,它们是动态加载的 DLL(总是用 RAD Studio 编写的)this technique.
现在,在其中一个插件中,我需要反射功能。虽然我似乎无法用 C++ 实现它们(在我无法修改的第三方 COM DLL 上需要反射),但我决定用 C# 重写这个 插件(它具有强大的反射功能) , 从而创建一个 .NET 程序集.
我知道我应该通过 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 语言编写。在这里,我有如下所示的托管 class,其中实现了程序集的真正逻辑。
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
编译器选项。它只是一个 "bridge" 项目,它依赖于 MyDllCore 项目并且只有一个 .cpp 或 .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());
我有一个使用 RAD Studio (C++Builder) XE4 开发的 C++ Windows 应用程序。它有一些插件,它们是动态加载的 DLL(总是用 RAD Studio 编写的)this technique.
现在,在其中一个插件中,我需要反射功能。虽然我似乎无法用 C++ 实现它们(在我无法修改的第三方 COM DLL 上需要反射),但我决定用 C# 重写这个 插件(它具有强大的反射功能) , 从而创建一个 .NET 程序集.
我知道我应该通过 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 语言编写。在这里,我有如下所示的托管 class,其中实现了程序集的真正逻辑。
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
编译器选项。它只是一个 "bridge" 项目,它依赖于 MyDllCore 项目并且只有一个 .cpp 或 .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());