c++11实现DLL帮助类

用过DLL的人都会发现,在C++中调用dll中的函数有点繁琐,调用过程如下:在加载dll后还要定义一个对应的函数指针类型,接着调用GetProcAddress获取函数地址,再转成函数指针,最后调用函数

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

  用过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 .0;
    }

    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(2, 3) << 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(2, 3, "helloworld") << endl;
}

c++11实现DLL帮助类

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, 2, 3);
    string str1 = "MultParmFun";
    float b = ExcecuteFunc<float(int,float,char*)>(hMoudle, str1, 2, 3.2, (char *)"helloworld");
}

c++11实现DLL帮助类

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/120132.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 最全面的外包公司的解释

    最全面的外包公司的解释1.最新北京软件外包公司排行榜软件外包企业排名:北京华盛恒辉科技有限公司(北京)北京五木恒润科技有限公司(北京)东软集团Neusoft(沈阳)博彦科技BeyondSoft(北京)海辉软件HiSoft(大连)文思VanceInfo(北京)浙大网新Insigma(杭州)奥博杰天Objectiva(北京)浪潮Inspur(济南)软通动力iSoftStone(北京)2.国内一些比…

    2022年5月29日
    46
  • Laravel Class config does not exist in

    Laravel Class config does not exist in

    2021年10月26日
    43
  • Java学习路线总结(书籍、视频推荐篇)[通俗易懂]

    Java学习路线总结(书籍、视频推荐篇)[通俗易懂]立志存高远,笃行践初心三更灯火五更鸡,正是男儿读书时。黑发不知勤学早,白首方悔读书迟。立志,标定人生方向;奋斗,创造人生价值,二者相辅相成,互相促进。大部分程序员的「目标」都是成为一名优秀的工程师,一名可以统览全局的「架构师」。千里之行始于足下对于大部分普通人而言,成为一名优秀的架构师还是有一定难度的,「千里之行始于足下,一步一个脚印,慢慢来」。????粉丝专属福利:包邮送书3本,如下书单四选一。????获取方式:1、参与文末投票,点赞,收藏即有机会获得精美图书一

    2022年5月16日
    43
  • mysql索引详解「建议收藏」

    一、MySQL三层逻辑架构MySQL的存储引擎架构将查询处理与数据的存储/提取相分离。下面是MySQL的逻辑架构图:一、对比InnoDB与MyISAM1、存储结构MyISAM:每个MyISAM在磁盘上存储成三个文件。分别为:表定义文件、数据文件、索引文件。第一个文件的名字以表的名字开始,扩展名指出文件类型。.frm文件存储表定义。数据文件的扩展名为.MYD(MYData)。索引文件的扩展名是.MYI(MYIndex)。InnoDB:所有的表都保存在同一个数据文件中(也可能是多个

    2022年4月18日
    51
  • 机房效果图制作|简易制作教程赘述

    机房效果图制作|简易制作教程赘述首先看图,这个图是人视角度,两侧显露出来的空间很大,注重表现的是两侧的机柜,包含列头柜,精密空调及上方的冷通道。第一步:客户肯定得提供图纸类的资料,如CAD图纸,或是手绘的平面布置图等。这里面需要包含机房的数量,排列组合为止或是模块化设置。第二步:拿到资料,和客户沟通之后,首先要明白客户表现的是什么效果,哪个地方是侧重点等。第三步:沟通完了就需要进行下一步,就是如果客户提供了CAD图纸

    2022年5月5日
    76
  • js对数字数组排序[通俗易懂]

    js对数字数组排序[通俗易懂]js中经常需要用到对数组进行排序的操作,当数组中的元素均为数字时,直接使用sort()进行排序得到的结果可能不是你想要的结果。假如我有数组arrayNums=[15,2,16],直接使用arrayNums.sort()的排序结果将是[15,16,2],这是因为Javascript的sort()函数在默认情况下是按照字符串顺序对值进行排序的。正因如此,sort()方法在对数值排序时会产生…

    2022年5月15日
    41

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号