用过DLL的人都会发现,在C++中调用dll中的函数有点繁琐,调用过程如下:在加载dll后还要定义一个对应的函数指针类型,接着调用GetProcAddress获取函数地址,再转成函数指针,最后调用函数。如果一个dll中有上百个函数,这中繁琐的定义会让人不胜其烦,下面将使用C++新特性中的多参数模版、function和type_traits结合起来山西爱你一个通用的dll帮助类。

1. win32 dll创建

1.1 mydll.h

#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif extern "C" MYDLL_API int Add(int, int);
extern "C" MYDLL_API float MultParmFun(int, float, char*);

1.2 mydll.cpp

#include "stdafx.h"
#include "mydll.h" #include <iostream>
using namespace std; MYDLL_API int Add(int a, int b)
{
cout << "entered:" << __FUNCTION__ << endl;
cout << "参数分别为:" << a << " "<< b << endl;
return a + b;
} MYDLL_API float MultParmFun(int a, float b, char* pBuff)
{
cout << "entered:" << __FUNCTION__ << endl;
cout << "参数分别为:" << a << " " << b << " "<< pBuff<< endl;
if (!pBuff)
{
return .;
} return a * b;
}

2. dll导出函数调用一般方法

#include "stdio.h"
#include <windows.h>
#include <string>
#include <codecvt>
#include <iostream>
using namespace std; string UncodeToAnsi(wstring &wstr)
{
wstring_convert<codecvt<wchar_t, char, mbstate_t>> convert(new codecvt<wchar_t, char, mbstate_t>("CHS"));
return convert.to_bytes(wstr);
} wstring AnsiToUnicode(string &str)
{
wstring_convert<codecvt<wchar_t, char, mbstate_t>> convert(new codecvt<wchar_t, char, mbstate_t>("CHS"));
return convert.from_bytes(str);
} void main()
{
HMODULE hMode = LoadLibrary(L"mydll");
if (!hMode)
{
return;
} typedef int(*Add)(int, int);
wstring wstr = L"Add";
string str = UncodeToAnsi(wstr);
Add AddFun = (Add)GetProcAddress(hMode, str.c_str());
cout << AddFun(, ) << endl; typedef float(*MultParm)(int, float, char*);
wstring wstr1 = L"MultParmFun";
string str1 = UncodeToAnsi(wstr1);
MultParm MultParmFun = (MultParm)GetProcAddress(hMode, str1.c_str());
cout << MultParmFun(, , "helloworld") << endl;
}

3. DLL帮助类的实现

3.1 代码实现

#pragma once

/*
DLL函数调用帮助类 实现的关键:
如何将一个FARPROC变成一个函数指针赋值给function,然后再调用可变参数执行,
函数的返回值通过std::result<function<T>(ARGS...)>来泛化,使得不同的dll
函数都可以用相同的方法来调用 需解决以下几个问题:
1.函数定义
2.函数调用多参数
3.返回值
*/ #include<functional>
#include<string>
using namespace std; #include "mydll.h"
#include <windows.h> bool InitDllHandle(HMODULE &hModule)
{
hModule = LoadLibrary(L"mydll");
if (!hModule)
{
return false;
}
return true;
} template<typename T>
function<T> GetFunction(HMODULE &hModule, string &strFunName)
{
FARPROC funAddress= (FARPROC)GetProcAddress(hModule, strFunName.c_str()); return function<T>((T*)funAddress);
} template<typename T, typename ...ARGS>
typename result_of<function<T>(ARGS...)>::type ExcecuteFunc(HMODULE &hModule, string &strFunName, ARGS ...args)
{
function<T> fun = GetFunction<T>(hModule, strFunName);
return fun(args...);
}

3.2 测试

#include "stdio.h"

#include "DllHelper.h"

#include <string>
#include <codecvt>
#include <iostream>
using namespace std; string UncodeToAnsi(wstring &wstr)
{
wstring_convert<codecvt<wchar_t, char, mbstate_t>> convert(new codecvt<wchar_t, char, mbstate_t>("CHS"));
return convert.to_bytes(wstr);
} wstring AnsiToUnicode(string &str)
{
wstring_convert<codecvt<wchar_t, char, mbstate_t>> convert(new codecvt<wchar_t, char, mbstate_t>("CHS"));
return convert.from_bytes(str);
} void main()
{
HMODULE hMoudle;
bool bResult = InitDllHandle(hMoudle);
if (!bResult)
{
cout << "句柄为空!" << endl;
}
string str = "Add";
int a = ExcecuteFunc<int(int, int)>(hMoudle, str, , );
string str1 = "MultParmFun";
float b = ExcecuteFunc<float(int,float,char*)>(hMoudle, str1, , 3.2, (char *)"helloworld");
}

c++11实现DLL帮助类的更多相关文章

  1. C#加载dll 创建类对象

    //加载dll 创建类对象string sqlightAssembly = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "syst ...

  2. DLL导出类避免地狱问题的完美解决方案

    DLL动态链接库是程序复用的重要方式,DLL可以导出函数,使函数被多个程序复用,DLL中的函数实现可以被修改而无需重新编译和连接使用该DLL的应用程序.作为一名面向对象的程序员,希望DLL可以导出类, ...

  3. DLL的概念、dll导出类(转贴)

    1. DLL的概念DLL(Dynamic Linkable Library),动态链接库,可以向程序提供一些函数.变量或类.这些可以直接拿来使用.静态链接库与动态链接库的区别:(1)静态链接库与动态链 ...

  4. C++ DLL导出类 知识大全

    在公司使用C++ 做开发,公司的大拿搭了一个C++的跨平台开发框架.在C++开发领域我还是个新手,有很多知识要学,比如Dll库的开发. 参考了很多这方面的资料,对DLL有一个基本全面的了解.有一个问题 ...

  5. 通过反射获取DLL的类实现加载窗体

    1.创建一个DLL 类库,并新建一个窗体类,这个直接在vs上操作就好 2. 建立一个Testassembly工程 新建一个测试类 namespace Testassembly { public par ...

  6. cmake 静态调用 c++ dll 的类的一个例子(Clion IDE)[更新1:增加1.模版的应用,2.ma 的算法]

    CMakeLists.txt project(aaa) add_library(aaa SHARED aaa.cpp) add_executable(bbb bbb.cpp) target_link_ ...

  7. DLL 导出类

    MyMathFun.h #pragma once // #ifdef DLLCLASS_API // #define DLLCLASS_API _declspec(dllimport) // #els ...

  8. [C++ Primer Plus] 第11章、使用类(一)程序清单——重载 P408

    程序清单11.4~11.6(运算符重载——添加加法运算符) //1.h class Time { private: int hours; int minutes; public: Time(); Ti ...

  9. Cuder - 用C++11封装的CUDA类

    以前写cuda:初始化环境,申请显存,初始化显存,launch kernel,拷贝数据,释放显存.一个页面大部分都是这些繁杂但又必须的操作,有时还会忘掉释放部分显存. 今天用C++11封装了这些CUD ...

随机推荐

  1. 大话Spark(3)-一图深入理解WordCount程序在Spark中的执行过程

    本文以WordCount为例, 画图说明spark程序的执行过程 WordCount就是统计一段数据中每个单词出现的次数, 例如hello spark hello you 这段文本中hello出现2次 ...

  2. InnoDB: The Auto-extending innodb_system data file './ibdata1' is of a different size 640 pages (rounded down to MB) than specified in the .cnf file: initial 768 pages, max 0 (relevant if non-zero) pa

    2016-09-14T09:17:37.713955Z 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleane ...

  3. 框架-数据库定义MD5加密

    1.--定义Md5加密declare @pt_pwd varchar(50)set @pt_pwd = ''set @pt_pwd = substring(sys.fn_sqlvarbasetostr ...

  4. android 获得屏幕状态

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools= ...

  5. linux命令stat,查看文件详细信息

    可以查看文件的各类具体信息:文件权限的数字形式0664:uid.gid的权限的数字形式等 更多用法参考stat --help lsattr test.sh 查看文件的其他属性:只读属性.只可以追加写属 ...

  6. 十步叫你如何无损修复硬盘锁(mbr病毒)

    经常看见有人被锁硬盘  开机以后出现一行红字 FUCK  YOU POJIEZHE  等等云云的 这个问题主要还是病毒对Mbr分区的修改造成的 下面我教给大家一个无损数据   无损硬盘  无需重装系统 ...

  7. SolidEdge如何绘制变化半径倒圆角

    1 在要变化半径的边上打一些点   2 点击倒角命令的参数对话框,选择可变半径   3 选择倒角的直线,右击确认,再依次点击关键点,修改倒角数值,修改之后按回车,继续下一个点,直到结束.  

  8. Android App 隐藏标题栏+状态栏+导航栏

    1. 隐藏当前Activity标题栏 在当前Activity中调用:this.requestWindowFeature(Window.FEATURE_NO_TITLE); 2. 隐藏当前Activit ...

  9. struts.xml中为什么加上<constant name="struts.devMode" value="true" />就出错

    严重: Exception starting filter struts2 java.lang.NullPointerException at com.opensymphony.xwork2.util ...

  10. javascript参数arguments对象

    ECMAScript函数的参数与大多树其他语言中函数的参数有所不同.ECMAScript函数不介意传递进来多少个参数,也不在乎传进来参数是什么类型.函数体是通过arguments对象来访问参数数组.a ...