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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 大学四年,从小白到大神,全网最硬核算法学习攻略,不接受反驳

    大学四年,从小白到大神,全网最硬核算法学习攻略,不接受反驳一道题做半天,另外半天看这道题的题解,一台电脑一包烟,一道题解整一天,是我智商有问题吗?刷了两年题之后,我可以负责任跟你说,刷题吃力很正常,学算法,刷leetcode不是一朝一夕的事情,需要一个过程。而且新手学算法,还很容易陷入一些误区,例如一上来就抱着《算法导论》这种天书,啥数据结构还没学,就去刷leetcode,这其实不好,只会让自己放弃算法。学习算法,应该要一步一步来,要有规划,下面给大家分享下我的算法学习经验吧,觉得有帮助给我点个赞就行了。一、刷题前的一些准备如果你连最基本的数据结

    2022年6月19日
    24
  • Qt5.7 + VS2015 环境搭建「建议收藏」

    Qt5.7 + VS2015 环境搭建「建议收藏」简述之前介绍过Qt5.x的环境搭建,5.7开始支持VS2015,为了使用新的开发环境(典型的强迫症),不得不再次进行Qt5.7+VS2015的环境搭建。除了之前介绍的搭建细节之外,其实中间有很多需要注意的部分。下面,主要分享搭建过程以及其中需要注意的一些事项。简述安装VS2015安装Qt57配置QtCreator配置编译器配置调试器HelloWorldVS20

    2022年5月16日
    64
  • Don’t Panic! KRACK 没你想象的那么糟

    Don’t Panic! KRACK 没你想象的那么糟上海交通大学密码与计算机安全实验室(LoCCS)软件安全小组(GoSSIP)版权所有,转载请与作者取得联系!著名的计算机学术安全会议CCS在2017年录用了一篇名为KeyReinstallationAttacks:ForcingNonceReuseinWPA2的学术论文,看起来,这和其他的上百篇同样将要在11月1日在美国达拉斯喜来登酒店会议中心一起登场报告的论文没有太大的差…

    2022年5月2日
    41
  • HTTP 协议入门

    HTTP 协议入门

    2021年11月4日
    42
  • Gloand 2021 激活码【2021.10最新】

    (Gloand 2021 激活码)JetBrains旗下有多款编译器工具(如:IntelliJ、WebStorm、PyCharm等)在各编程领域几乎都占据了垄断地位。建立在开源IntelliJ平台之上,过去15年以来,JetBrains一直在不断发展和完善这个平台。这个平台可以针对您的开发工作流进行微调并且能够提供…

    2022年3月28日
    48
  • qsettings删除注册表_QSettings使用方法

    qsettings删除注册表_QSettings使用方法一 QSettings 介绍 用户通常希望应用程序记住其设置 在 windows 中 这些设置保存在注册表中 ios 在属性文件列表中 而 unix 在缺乏标准的情况下 其存储在 ini 文本中 QSettings 有两种存储格式 QSettings NativeFormat 在 windows 平台可读写注册表 QSettings IniFormat 读写 ini 文件 QSettings InvalidF

    2025年10月18日
    4

发表回复

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

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