此技术目前基本属于过时状态,除了使用MFC开发有一定作用外,其他基本没有作用。
与Windows平台十分耦合的调用。
技术原理:
- 使用std::map缓存装载的函数
- 使用变长参数模板获取Win32函数调用
3.使用std::result_of获取函数返回值
程序代码如下,
mydll.h
#ifndef _MY_DLL_H_
#define _MY_DLL_H_
extern "C" __declspec(dllexport) int Add(int &a, int &b);
extern "C" __declspec(dllexport) int Max(const int &a, const int &b);
extern "C" __declspec(dllexport) int Get(const int &a);
#endif
dll_parser.hpp
#ifndef _DLL_PARSER_H_
#define _DLL_PARSER_H_
#include <windows.h>
#include <string>
#include <functional>
#include <map>
#include <iostream>
#include <exception>
using std::cout;
using std::endl;
using std::map;
using std::string;
class DLLParser {
public:
DLLParser() {}
~DLLParser() {
Unload();
}
bool Load(const string& dllPath) {
m_hMod = LoadLibrary(LPCTSTR(dllPath.c_str()));
if(nullptr == m_hMod) {
cout << "LoadLibrary failed" << endl;
return false;
}
return true;
}
template <typename T, typename ... Args>
typename std::result_of<std::function<T>(Args...)>::type
ExecuteFunc(const string& funcName, Args&& ... args) {
auto f = GetFunction<T>(funcName);
if(f == nullptr) {
string s = "Can not find this function " + funcName;
throw std::logic_error(s);
}
return f(std::forward<Args>(args)...);
}
private:
bool Unload() {
// 说明已经被卸载
if(m_hMod == nullptr) {
return true;
}
auto b = FreeLibrary(m_hMod);
// 说明free失败
if(!b) {
return false;
}
m_hMod = nullptr;
return true;
}
template <typename T>
T* GetFunction(const string& funcName) {
auto funcIt = m_map.find(funcName);
if(funcIt != m_map.end()) {
auto func = funcIt->second;
return (T*)func;
}
auto addr = GetProcAddress(m_hMod, funcName.c_str());
m_map.emplace(funcName, addr);
return (T*)addr;
}
private:
HMODULE m_hMod;
map<string, FARPROC> m_map;
};
#endif
main.cpp
#include "dll_parser.hpp"
#include <cstdlib>
void TestDllParser() {
DLLParser parser;
string s = "mydll.dll";
// 加载 dll
parser.Load(s);
int a = 5;
int b = 8;
auto max = parser.ExecuteFunc<int(const int&, const int&)>("Max", a , b);
cout << "Max(5, 8): " << max << endl;
a = 7;
b = 3;
max = parser.ExecuteFunc<int(const int&, const int&)>("Max", a, b);
cout << "Max(7, 3): " << max << endl;
auto add = parser.ExecuteFunc<int(int&, int&)>("Add", a, b);
cout << "Add(7, 3): " << add << endl;
}
int main(void) {
TestDllParser();
cout << "请按任意键继续..." << endl;
getchar();
return 0;
}
Makefile如下,
TAR=main
WORKSPACE_DIR=.
CC:=g++
LIB_PATH =-L.
.PHONY: build clear all
build:
$(CC) -std=c++11 $(WORKSPACE_DIR)/mydll.h $(WORKSPACE_DIR)/main.cpp -g -o $(TAR) $(LIB_PATH)
all: clear build
clear:
rm -rf $(TAR)
程序输出如下
图片.png
网友评论