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


相关推荐

  • 初识ABP vNext(7):vue身份认证管理&租户管理

    初识ABP vNext(7):vue身份认证管理&租户管理

    2020年11月20日
    144
  • map的遍历方式「建议收藏」

    map的遍历方式「建议收藏」@org.junit.TestpublicvoidtestHashMap(){Map<String,String>map=newHashMap<>(4);

    2022年7月3日
    31
  • mysql主从复制周期_Mysql主从复制[通俗易懂]

    mysql主从复制周期_Mysql主从复制[通俗易懂]Mysql主从复制背景:Mysql可以实现主从复制,在学习了Mysql主从复制后,将一些如何主从复制过程记录下来,供以后复习使用。准备:在做Mysql的主从复制前需要做一些准备工作:1、同步时间做主从的服务器的时间需要同步,不然会出问题。命令:ntpdateip(ntpdate命令需要先安装ntpdate)2、版本一致做主从的Mysql服务需要版本一致,或者从服务器的版本高于主服务器。主从复制…

    2022年8月13日
    2
  • (数据库)数据库分类

    (数据库)数据库分类1.面向操作的关系型数据库典型性应用领域:ERP,CRM,信用卡交易,中小型电商数据储存方法:表格流行厂商:OracleDatabase,MicrosoftSQLServer,IBMDB2,EnterpriseDB(PostgreSQL),MySQL优点:完善的生态环境保护,事务保证/数据一致性缺点:严苛的数据模型界定,数据库拓展限制,和非结构型的结合应用较难。2.面向数据分析的关系型数据库典型性应用领域:数据仓库,商务智能,数据科学研究数据储存方法:表格流行厂商:OracleE

    2022年6月24日
    25
  • 怎么改变pycharm的背景颜色_pycharm设置成白底

    怎么改变pycharm的背景颜色_pycharm设置成白底进入软件点击File选择Settings点击点击Edito左下角的三角形点击ColorScheme左下角的三角形选择ConsoleFoot点击点击Scheme的选择框选择完毕之后点Ok,会弹出一个选择框,yes代表全部改变,no代表编辑框的背景颜色改变

    2022年8月26日
    7
  • dojo加载树错误

    dojo加载树错误

    2022年1月8日
    44

发表回复

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

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