从DLL动态加载任意函数到std::function
C++ Dynamically load arbitrary function from DLL into std::function
如何使用单个函数将任意动态链接库 (dll)函数加载到std::function
对象中?
例如,我想将两个函数编译成dll:
// test.dll
int plusFive(int value) {
return value + 5;
}
void printHello() {
std::cout << "Hello!" << std::endl;
}
并在运行时使用一个函数加载它们,像这样:
// main.cc
#include <functional>
int main() {
std::function<int(int)> func1(loadDllFunc("test.dll", "plusFive"));
std::function<void()> func2(loadDllFunc("test.dll", "printHello"));
}
使用windows.h
中提供的WinAPI函数(描述取自MSDN Dev Center)
-
LoadLibrary
-将指定模块加载到调用进程的地址空间中。返回一个句柄到模块。 -
GetProcAddress
-从指定的动态链接库(DLL)中检索导出函数或变量的地址。返回导出函数或变量的地址。
使用这个函数来加载一个特定的函数并返回一个std::function
对象:
// main.cc
#include <iostream>
#include <string>
#include <functional>
#include <windows.h>
template <typename T>
std::function<T> loadDllFunc(const std::string& dllName, const std::string& funcName) {
// Load DLL.
HINSTANCE hGetProcIDDLL = LoadLibrary(dllName.c_str());
// Check if DLL is loaded.
if (hGetProcIDDLL == NULL) {
std::cerr << "Could not load DLL "" << dllName << """ << std::endl;
exit(EXIT_FAILURE);
}
// Locate function in DLL.
FARPROC lpfnGetProcessID = GetProcAddress(hGetProcIDDLL, funcName.c_str());
// Check if function was located.
if (!lpfnGetProcessID) {
std::cerr << "Could not locate the function "" << funcName << "" in DLL"" << dllName << """ << std::endl;
exit(EXIT_FAILURE);
}
// Create function object from function pointer.
std::function<T> func(reinterpret_cast<__stdcall T*>(lpfnGetProcessID));
return func;
}
DLL源代码应该这样写:
// test.cc (test.dll)
#include <iostream>
// Declare function prototypes with "extern C" to prevent name mangling.
// Declare functions using __declspec(dllexport) to signify the intent to export.
extern "C" {
__declspec(dllexport) int __stdcall plusFive(int);
__declspec(dllexport) void __stdcall printHello();
}
int plusFive(int value) {
return value + 5;
}
void printHello() {
std::cout << "Hello!" << std::endl;
}
然后像这样使用loadDllFunc
:
// main.cc
int main() {
auto func1 = loadDllFunc<int(int)>("test.dll", "plusFive");
auto func2 = loadDllFunc<void()>("test.dll", "printHello");
std::cout << "Result of func1: " << func1(1) << std::endl;
func2();
}
输出:Result of func1: 6
Hello!
作为旁注,DLL可以像这样使用GCC(4.7.2)编译:
g++ -shared -o test.dll test.cc -std=c++11
编辑:
我不确定loadDllFunc
中的转换是否给出了正确的类型:
std::function<T> func(reinterpret_cast<__stdcall T*>(lpfnGetProcessID));
当它应该是int (__stdcall *)(int)
时,它似乎将其强制转换为__stdcall int (*)(int)
。
loadDllFunc
的另一种方法。此解决方案将正确地将函数指针强制转换为int (__stdcall *)(int)
。
template <typename T>
struct TypeParser {};
template <typename Ret, typename... Args>
struct TypeParser<Ret(Args...)> {
static std::function<Ret(Args...)> createFunction(const FARPROC lpfnGetProcessID) {
return std::function<Ret(Args...)>(reinterpret_cast<Ret (__stdcall *)(Args...)>(lpfnGetProcessID));
}
};
template <typename T>
std::function<T> loadDllFunc(const std::string& dllName, const std::string& funcName) {
// Load DLL.
HINSTANCE hGetProcIDDLL = LoadLibrary(dllName.c_str());
// Check if DLL is loaded.
if (hGetProcIDDLL == NULL) {
std::cerr << "Could not load DLL "" << dllName << """ << std::endl;
exit(EXIT_FAILURE);
}
// Locate function in DLL.
FARPROC lpfnGetProcessID = GetProcAddress(hGetProcIDDLL, funcName.c_str());
// Check if function was located.
if (!lpfnGetProcessID) {
std::cerr << "Could not locate the function "" << funcName << "" in DLL"" << dllName << """ << std::endl;
exit(EXIT_FAILURE);
}
// Create function object from function pointer.
return TypeParser<T>::createFunction(lpfnGetProcessID);
}
相关文章:
- 使用std::函数映射对象方法
- 可组合的lambda/std::函数与std::可选
- 当使用透明的std函数对象时,我们还需要写空的尖括号吗
- std::函数常量正确性未遵循
- 具有变量Number of Arguments的std::函数的矢量
- 从类型std::函数传递变量失败,尽管调用方期望的类型完全相同
- 如何调用存储在指向"std::函数"的指针中的 lambda?
- C++ STD 函数运算符:有没有一种方法可以通过函数将一个向量映射到另一个向量上?
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 如何将类 1 的 std::函数绑定到类 2 的函数?
- 如何制作可以接受任何类型的参数的 std::函数和 lambda
- 如何将 STL 队列推送函数绑定到 std::函数?
- std::函数不起作用,但普通的旧函数指针可以 - 为什么?
- 获取 std::函数以推断按引用传递/按值传递
- std::bind 和 std::函数术语不值为接受 0 个参数?
- 从其存储的回调中删除 std::函数是否安全
- 创建 std::函数,它返回具有函数成员值的变量.分段错误
- 创建一个带有 lambda 的 std::函数,而不知道函数的参数
- std::函数的解释
- 在调用过程中删除 std::函数