起因

开发中经常需要动态调用一些导出函数,试着利用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导出函数的更多相关文章

  1. python利用or在列表解析中调用多个函数.py

    python利用or在列表解析中调用多个函数.py """ python利用or在列表解析中调用多个函数.py 2016年3月15日 05:08:42 codegay & ...

  2. DLL模块例1:使用.def模块导出函数,规范修饰名称,显示连接调用dll中函数

    以下内容,我看了多篇文章,整合在一起,写的一个例子,关于dll工程的创建,请参考博客里另一篇文章:http://www.cnblogs.com/pingge/articles/3153571.html ...

  3. AFX_MANAGE_STATE(AfxGetStaticModuleState())DLL导出函数包含MFC资源

    AFX_MANAGE_STATE(AfxGetStaticModuleState()) 先看一个例子: .创建一个动态链接到MFC DLL的规则DLL,其内部包含一个对话框资源.指定该对话框ID如下: ...

  4. dll 导出函数名的那些事

    dll 导出函数名的那些事 关键字: VC++  DLL  导出函数 经常使用VC6的Dependency或者是Depends工具查看DLL导出函数的名字,会发现有DLL导出函数的名字有时大不相同,导 ...

  5. C# 遍历DLL导出函数

    C#如何去遍历一个由C++或E语言编写的本地DLL导出函数呢 不过在这里我建议对PE一无所知的人 你或许应先补补这方面的知识,我不知道为什么PE方面的 应用在C#中怎么这么少,我查阅过相关 C#的知识 ...

  6. Dll 导出函数那些破事

    经常使用VC6的Dependency查看DLL导出函数的名字,会发现有DLL导出函数的名字有时大不相同,导致不同的原因大多是和编译DLL时候指定DLL导出函数的界定符有关系. VC++支持两种语言:即 ...

  7. DLL导出函数和类的定义区别 __declspec(dllexport)

    DLL导出函数和类的定义区别 __declspec(dllexport) 是有区别的, 请看 : //定义头文件的使用方,是导出还是导入 #if defined(_DLL_API) #ifndef D ...

  8. dll导出函数的两种方式的比较

    最初的网页链接已经挂了, 在此贴一个中间的转载链接 https://blog.csdn.net/zhazhiqiang/article/details/51577523 一 概要 vs中导出 dll的 ...

  9. DLL导出函数

    使用DEF文件从DLL导出 模块定义(.def)文件时包含一个或多个描述DLL各种属性的Module语句的文本文件.如果不使用_declspec(dllexport)关键字导出DLL的函数,则DLL需 ...

随机推荐

  1. Nebula 基于 ElasticSearch 的全文搜索引擎的文本搜索

    本文首发于 Nebula Graph 公众号 NebulaGraphCommunity,Follow 看大厂图数据库技术实践. 1 背景 Nebula 2.0 中已经支持了基于外部全文搜索引擎的文本查 ...

  2. 【NX二次开发】创建扫描特征

    扫描特征相关函数: 创建扫描特征的相关函数: 1.UF_MODL_create_extrude_trim_opts 拉伸 2.UF_MODL_create_extrude_trim_opts1 拉伸 ...

  3. Selective Kernel Networks

    摘要:在标准的卷积神经网络(CNNs)中,每一层的人工神经元的感受野被设计成具有相同的大小.众所周知,视觉皮层神经元的感受野大小受刺激的调节,但在构建cnn时却很少考虑到这一点.我们在神经网络中提出了 ...

  4. 题解 P3233 [HNOI2014]世界树

    题目传送门 解题思路 正解当然是虚树了. 首先对于原树以及虚树各开一个结构体存边,这个不用多说. 然后我们先 DFS 一遍,求出各个节点的时间戳,子树大小,深度以及父亲节点,并初始化倍增 LCA . ...

  5. 【模拟8.11】将军令(贪心&&树形DP)

    只看45分的话,是树形DP....(当然也有能拿到70分+的大佬) 40分: 只考虑k==1的情况,树形DP 所以每个节点可能被父亲,自己,儿子控制 设f[MAXN][3],0表示儿子,1表示自己,2 ...

  6. C#WebService的创建与发布

    VS中新建项目-Web-ASP.NET Web应用程序 然后确定,选择空模版就可以了 其中CRMService.asmx是点击项目新建Web服务(asmx) 这样基本的功能就能用了,然后就是发布 点击 ...

  7. excel VBA根据单元格内的逗号把内容拆分行

    Sub test1()    Dim h    Dim j As Integer    j = 0  '用于辅助循环的进行,可以在拆分行获取下一个需要拆分单元格的行号    'Application. ...

  8. php+redis实现全页缓存系统

    php redis 实现全页缓存系统之前的一个项目说的一个功能,需要在后台预先存入某个页面信息放到数据库,比如app的注册协议,用户协议,这种.然后在写成一个php页面,app在调用接口的时候访问这个 ...

  9. php微信jsapi支付 支付宝支付 两码合一

    产品开会提出了这样的需求:一个二维码可以微信支付也可以支付宝支付 经过自己的钻研以及询问技术高人(本人代码一般般)和网上搜索 最终实现其功能  我用微信jsapi 和 支付宝网页支付 其实并不怎么难: ...

  10. NTP时间服务器配置

    1.服务器端配置: #允许这些IP向自己同步时间 restrict x.x.x.x mask x.x.x.x nomodiy notrap #当和定义的所有server服务器无法同步后,和自身同步 s ...