利用C++11可变模板,封装调用dll导出函数
起因
开发中经常需要动态调用一些导出函数,试着利用C++11特性封装一下
尝试
常规使用
typedef int WINAPI (*TMessageBoxA)(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType);
if (HMODULE m = LoadLibraryA("user32")) {
if (FARPROC proc = GetProcAddress(m,"MessageBoxA")) {
TMessageBoxA msgBox = reinterpret_cast<TMessageBoxA>(fn);
msgBox(0,0,0,0); // call it ...
}
FreeLibrary(m);
}
流程很清晰,只是写多了看着不爽
曾经利用 decltype function bind 实现过另个版本,这次尝试更纯粹一些
解决
参考std::function实现方式,仅使用"Variadic Templates"
#include <windows.h>
template<typename _T> class Api;
template<typename _Res, typename... _ArgTypes>
class Api<_Res(_ArgTypes...)> {
public:
Api(const char* dllName, const char* funcName) {
_M_module = LoadLibraryA(dllName);
_M_func = reinterpret_cast<_Func>(GetProcAddress(_M_module, funcName));
}
~Api() {
if (_M_module) FreeLibrary(_M_module);
}
_Res operator()(_ArgTypes... __args) const {
return _M_func(__args...);
}
private:
typedef _Res (*_Func)(_ArgTypes...);
_Func _M_func;
HMODULE _M_module;
};
int main()
{
Api<int(HWND,LPCTSTR,LPCTSTR,UINT)> msgbox("user32", "MessageBoxA");
msgbox(0,0,0,0);
}
注意,为了最小利用特性,这里没有利用final、delete进行使用限制,也没有对HMODULE进行缓存管理,生产环境请自行抉择。
有更好的方式,请留言交流;-)
还是附上另一种更常用的方法
#include <map>
#include <string>
#include <functional>
#include <windows.h>
class WinDll {
public:
WinDll(const char* dll) {
mMoudle = LoadLibraryA(dll);
}
WinDll(const wchar_t* dll) {
mMoudle = LoadLibraryW(dll);
}
~WinDll() {
if (mMoudle) FreeLibrary(mMoudle);
}
FARPROC RawApi(const std::string& fn) {
auto it = mFuncCaches.find(fn);
if (it == mFuncCaches.end()) {
FARPROC func = GetProcAddress(mMoudle, fn.c_str());
if (!func) throw "not found!";
mFuncCaches[fn] = func;
return func;
}
return it->second;
}
template<typename _T>
std::function<_T> ApiFunc(const std::string& fn) {
return std::function<_T>(reinterpret_cast<_T*>(RawApi(fn)));
}
private:
HMODULE mMoudle;
std::map<std::string,FARPROC> mFuncCaches;
};
int main()
{
WinDll user32("user32");
using TMessageBoxA = int(HWND,LPCTSTR,LPCTSTR,UINT);
auto msgBox = user32.ApiFunc<TMessageBoxA>("MessageBoxA");
msgBox(0,0,0,0);
}
利用C++11可变模板,封装调用dll导出函数的更多相关文章
- python利用or在列表解析中调用多个函数.py
python利用or在列表解析中调用多个函数.py """ python利用or在列表解析中调用多个函数.py 2016年3月15日 05:08:42 codegay & ...
- DLL模块例1:使用.def模块导出函数,规范修饰名称,显示连接调用dll中函数
以下内容,我看了多篇文章,整合在一起,写的一个例子,关于dll工程的创建,请参考博客里另一篇文章:http://www.cnblogs.com/pingge/articles/3153571.html ...
- AFX_MANAGE_STATE(AfxGetStaticModuleState())DLL导出函数包含MFC资源
AFX_MANAGE_STATE(AfxGetStaticModuleState()) 先看一个例子: .创建一个动态链接到MFC DLL的规则DLL,其内部包含一个对话框资源.指定该对话框ID如下: ...
- dll 导出函数名的那些事
dll 导出函数名的那些事 关键字: VC++ DLL 导出函数 经常使用VC6的Dependency或者是Depends工具查看DLL导出函数的名字,会发现有DLL导出函数的名字有时大不相同,导 ...
- C# 遍历DLL导出函数
C#如何去遍历一个由C++或E语言编写的本地DLL导出函数呢 不过在这里我建议对PE一无所知的人 你或许应先补补这方面的知识,我不知道为什么PE方面的 应用在C#中怎么这么少,我查阅过相关 C#的知识 ...
- Dll 导出函数那些破事
经常使用VC6的Dependency查看DLL导出函数的名字,会发现有DLL导出函数的名字有时大不相同,导致不同的原因大多是和编译DLL时候指定DLL导出函数的界定符有关系. VC++支持两种语言:即 ...
- DLL导出函数和类的定义区别 __declspec(dllexport)
DLL导出函数和类的定义区别 __declspec(dllexport) 是有区别的, 请看 : //定义头文件的使用方,是导出还是导入 #if defined(_DLL_API) #ifndef D ...
- dll导出函数的两种方式的比较
最初的网页链接已经挂了, 在此贴一个中间的转载链接 https://blog.csdn.net/zhazhiqiang/article/details/51577523 一 概要 vs中导出 dll的 ...
- DLL导出函数
使用DEF文件从DLL导出 模块定义(.def)文件时包含一个或多个描述DLL各种属性的Module语句的文本文件.如果不使用_declspec(dllexport)关键字导出DLL的函数,则DLL需 ...
随机推荐
- 设置NX欢迎界面
环境变量 变量名:UGII_WELCOME_PAGE 变量值:http://www.baidu.com/
- DHCP原理与配置
一.DHCP应用场景 DHCP服务器能够为大量主机分配lp地址,并能够集中管理 二.DHCP报文类型 微软操作系统的DHCP服务是四个广播报文 三.地址池 主机-------------------- ...
- 连接过的WiFi改了密码之后再次连接不让输入新密码还是用旧密码一直显示连接失败
设置---网络和Internet---WLAN----管理已知网络----忘记 根据这个步骤就能忘记密码,重新输入新密码了.
- String ,StringBuffer 与S tringBuilder的区别??
String 字符串常量StringBuffer 字符串变量(线程安全)StringBuilder 字符串变量(非线程安全) ------------------------------------- ...
- CapsuleAO实现的学习
正是一个炎夏,又到了整活的好时候.最近抽些时间研究下CapsuleAO,记述实践体会. 1.简介 这是一个通过在角色骨骼上绑定虚拟胶囊体并以数学方法实现胶囊近似的AO环境光遮蔽效果的方法, 当角色处于 ...
- Netty 框架学习 —— 添加 WebSocket 支持
WebSocket 简介 WebSocket 协议是完全重新设计的协议,旨在为 Web 上的双向数据传输问题提供一个切实可行的解决方案,使得客户端和服务器之间可以在任意时刻传输消息 Netty 对于 ...
- 使用 .net WEBAPI 返回 application/json类型导致 IE8 提示下载
1, 场景介绍 项目使用了 jquery.form.js这个插件,用 ajax的方式提交 form 表单里面的信息.因为需要使用 ajax获取到返回信息.数据录入使用的是 .net mvc方式的 we ...
- 通过修改Host实现chrome同步
问题原因 : 中国的GW屏蔽了google服务,导致无法同步账号信息,这是一个很好的功能.可以同步书签,插件等! 跟chrome的版本号无关,设置hosts文件就能够正常运行(文件位置 : C:\Wi ...
- 精尽Spring Boot源码分析 - 日志系统
该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...
- HMM实现中文分词
链接:https://pan.baidu.com/s/1uBjLC61xm4tQ9raDa_M1wQ 提取码:f7l1 推荐:https://blog.csdn.net/longgb123/arti ...