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帮助类

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • mac svn使用教程(linux 终端命令)

    使用Homebrew下载svnbrewinstallsvn查询svn下载路径并测试svn安装whichsvnsvn-version检出项目:先进入要检出的项目目录svncheckoutsvn地址

  • Idea生成Javadoc

    Idea生成Javadoc

  • Ubuntu安装谷歌_谷歌地球手机专业版

    Ubuntu安装谷歌_谷歌地球手机专业版在Ubuntu18.04中安装谷歌地球GoogleEarthGoogleEarth在Linux系统中(Ubuntu18.04)的安装方法1.安装必备组建2.下载GoogleEarth安装包3.安装GoogleEarth4.开启运行GoogleEarthGoogleEarth在Linux系统中(Ubuntu18.04)的安装方法1.安装必备组建使用gdebi在我们的系统上安装Goo…

  • mac全选文字的快捷键_MACBOOK最全快捷键指南

    mac全选文字的快捷键_MACBOOK最全快捷键指南官方最新出炉的快捷键大全:剪切、拷贝、粘贴和其他常用快捷键Command-X:剪切所选项并拷贝到剪贴板。Command-C:将所选项拷贝到剪贴板。Command-V:将剪贴板的內容粘贴到当前文稿或应用中。Command-Z:撤销前一个命令。随后您可以按Command-Shift-z来重做,从而反向执行撤销命令。Command-A:全选各项。Command-F:查找文稿中的项目或打开“查找”窗口。…

  • Linux 路由表详解及 route 命令详解

    Linux 路由表详解及 route 命令详解Linux内核的路由表通过route命令查看Linux内核的路由表:[root@VM_139_74_centos~]#routeKernelIProutingtableDestinationGatewayGenmaskFlagsMetricRefUseIfacedefaultgatewa…

  • ubuntu支持的文件系统类型_常见的文件系统有哪两种

    ubuntu支持的文件系统类型_常见的文件系统有哪两种文件系统类型在windows中我们常见的磁盘格式有fat16、fat32和ntfs。但是windows的文件管理显得有些赘余,为打开一个文件需要打开n个地方,在一个角落里找。而且windows本身对于其他系统的文件格式就更差了,没有听说在windows里打开ext3或者mac日志式。windows是一个封闭的系统。在ubuntu中其文件系统广泛使用ext3的文件格式,从而实现了将整个

发表回复

您的电子邮箱地址不会被公开。

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