本文使用的是dev-c++,如果涉及到VC++中不一样的操作,也会适当进行区分。

项目一:创建DLL

1、创建一个DLL类型的项目,当前命名为dlltest,并选择合适的路径进行保存。

 2、在生成的预设置代码中,加入如下代码

//这是头文件dll.h
#ifndef _DLL_H_
#define _DLL_H_ #if BUILDING_DLL
#define DLLIMPORT __declspec(dllexport)
#else
#define DLLIMPORT __declspec(dllimport)
#endif class DLLIMPORT DllClass
{
public:
DllClass();
virtual ~DllClass();
void HelloWorld(char* info);
}; extern "C"
{
DLLIMPORT int HW(int n);
} DLLIMPORT int func(int n);
#endif
/*这是主体文件dllmain.cpp */
#include "dll.h"
#include <windows.h> DllClass::DllClass()
{ } DllClass::~DllClass()
{ } void DllClass::HelloWorld(char* info)
{
MessageBox(0, info,"Hi",MB_ICONINFORMATION);
} DLLIMPORT int HW(int n)
{
return n;
} DLLIMPORT int func(int n)
{
return
n;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
{
switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
{
break;
}
case DLL_PROCESS_DETACH:
{
break;
}
case DLL_THREAD_ATTACH:
{
break;
}
case DLL_THREAD_DETACH:
{
break;
}
} /* Return TRUE on success, FALSE on failure */
return TRUE;
}

在上面的代码中,我们加入了HW和func两个导出函数,以及一个DllClass(自动生成)导出类。

点击编译后,我们可以在项目文件夹中,看到dlltest.dll,这就是我们需要的目标动态链接库。libdlltest.a则是vc里需要用到的lib文件。

3、extern "C"说明

当前可以用记事本打到libdlltest.def文件,可以看到如下内容:

加了extern "C"的HW函数地址偏移量还是HW,没有加extern "C"的func函数,地址偏移量变成了_Z4funci。这个地址在动态调用导出函数的过程中会用到。

项目二:动态调用dll导出的函数

1、再创建一个C++项目,将项目一生成的dll文件放入项目文件夹中:

 2、使用LoadLibrary和和GetProcAddress动态载入动态链接库,并调用导出的函数:

#include <iostream>
#include <windows.h>
using namespace std; int main()
{
HMODULE hMod=LoadLibrary("dlltest.dll");
if(hMod==NULL)
{
cerr<<"load lib error";
return 1;
} Func f=(Func)GetProcAddress(hMod,"HW");
cout<<f(200); FreeLibrary(hMod); return 0;
}

在GetProcAddress中,调用HW函数可以直接传入偏移量HW;

如果调用func函数,则要传入偏移量“_Z4funci”;因为func函数没有声明为extern "C"。

3、特别备注,当前这种方式无法使用LoadLibrary和GetProcAddress获出导出类。

因为GetProcAddress获取的是函数的地址偏移量,与类无关。为了可以动态使用导出的类,必须使用将一个纯虚函数做为基类,将导出创建和销毁类的函数。具体做法如下:

//dll.h
#include <stdlib.h>
#include <stdio.h> class virtualXXX
{
public:
virtual void functionOne() = 0;
virtual void functionTwo() = 0;
}; #if defined(_WINDOWS)
#ifdef XXX_API
#define XXX_API __declspec(dllexport)
#else
#define XXX_API __declspec(dllimport)
#endif
#else
#define XXX_API
#endif class XXX_API xxx : public virtualXXX
{
public:
void functionOne()
{
printf ( "One\n" );
} void functionTwo()
{
printf ( "Two\n" );
}
}; extern "C" XXX_API virtualXXX * create();
extern "C" XXX_API void delete_object( virtualXXX * p ); //dll.cpp
virtualXXX * create()
{
return ( new xxx() );
} void delete_object( virtualXXX * p )
{
if ( p )
{
delete p;
p = NULL;
}
}

动态调用:

#include <Windows.h>
typedef virtualXXX *(fun_create)(void);
fun_create* vc_create = NULL; int main()
{
HINSTANCE dllHandle = NULL;
dllHandle = LoadLibrary( "Win32_Test_dll.dll" );
vc_create = ( fun_create* )GetProcAddress( dllHandle,"create" );
virtualXXX * xxxHandle = vc_create(); xxxHandle->functionOne();
xxxHandle->functionTwo(); delete_object(xxxHandle);
}

这个方法参考文章C++动态库导出类,及使用,博主未实际进行测试。

项目三:静态调用导出的类

静态调用dll,在VC++需要头文件、dll和对应的lib文件(即项目一中生成的 libdlltest.a)。然后再使用#pragma comment(lib,"lib文件路径")对编译器进行配置lib路径,之后再进行调用。详细过程可以参考《c++生成DLL并调用》

本文着重调论Dev-C++下的静态调用。对于MinGW64静态调用dll,只需要dll文件和相关的头文件,项目结构如下:

其中main.cpp中调用类的代码如下:

#include <iostream>
#include <windows.h>
#include "dll.h"
using namespace std; int main()
{
DllClass c;
char str[]="hello";
c.HelloWorld(str); return 0;
}

可以看到,无需在代码中进行任何设置。因为只有在链接的过程c++才会去找DllClass这个类的真实地址。

在编译成exe时,有如下两种方法:

方法一、可以使用命令行进行编译:

通过cmd进入main.cpp所在文件夹路径,运行:g++ -o main.exe main.cpp -I . -L . -ldlltest

即可编译生成可执行文件exe。编译参数说明如下:

-I搜索头文件的目录
-I .在当前文件夹下搜索头文件
-L搜索动态库的目录
-L .在当前文件夹下搜索动态库

方法二、将参数加入编译选项中:

如果觉得用命令行编译太麻烦,可以将-I -L和-l加入Dev-C++的编译器选项中。

这样点击“编译运行”就可以正确找到对应的dll进行编译链接,正确生成exe文件。

本文关于Dev-C++创建并调用动态链接库dll到这里就结束了,欢迎大家指正:)

C++创建与调用dll动态链接库(MinGW64 Dev-C++)的更多相关文章

  1. VC++:创建,调用Win32动态链接库

    VC++:创建,调用Win32动态链接库 概述 DLL(Dynamic Linkable Library)动态链接库,Dll可以看作一种仓库,仓库中包含了可以直接使用的变量,函数或类.仓库的发展史经历 ...

  2. C#中调用Dll动态链接库

    C#中调用Dll动态链接库 起始 受限于语言的不同,我们有的时候可能会用别人提供的函数及方法 或者其他的什么原因.反正就是要调!!! 恰巧别人所使用的的语言跟自己又不是一样的 这个时候想要调用别人的函 ...

  3. VC++:创建,调用MFC动态链接库(扩展DLL)

    概述 DLL(Dynamic Linkable Library)动态链接库,Dll可以看作一种仓库,仓库中包含了可以直接使用的变量,函数或类. 仓库的发展史经历了"无库" ---& ...

  4. Java使用JNA方式调用DLL(动态链接库)(原创,装载请注明出处)

    Java使用JNA调用DLL 1.准备 1.JDK环境 2.Eclipse 3.JNA包 下载JNA包: (1).JNA的Github:https://github.com/java-native-a ...

  5. 在VC中创建并调用DLL

    转自:http://express.ruanko.com/ruanko-express_45/technologyexchange6.html 一.DLL简介 1.什么是DLL? 动态链接库英文为DL ...

  6. c#下调用dll动态链接库[转]

    C# 调用传统的 API 动态链接库,是.NET开发经常被讨论的问题. 比如有这么一个动态链接库(delphi 语言): library DelphiDLL; uses SysUtils, Class ...

  7. VC++创建、调用dll的方法步骤

    文章来源:http://www.cnblogs.com/houkai/archive/2013/06/05/3119513.html 代码复用是提高软件开发效率的重要途径.一般而言,只要某部分代码具有 ...

  8. VS2015环境下生成和调用DLL动态链接库

    一.生成动态链接库: 1.打开VS2015->文件->新建->项目->Visual C++->Win32->Win32控制台应用程序->将名称改为dll_ge ...

  9. VBA 调用DLL动态链接库

    在ArcMap中引用动态链接库       我在VB6下编译生成了一个动态链接库文件VBAPrj.dll,其中有一类模块VBACls,此类模块有一个方法Test(Doc As Object).     ...

  10. Windows下C语言调用dll动态链接库

    dll是windows下的动态链接库文件,下面记录一下在windows下如何调用C语言开发的dll动态链接库. 1.dll动态链接库的源代码 hello_dll.c #include "st ...

随机推荐

  1. SpringBoot彩蛋之定制启动画面

    写在前面 在日常开发中,我们经常会看到各种各样的启动画面.例如以下几种 ① spring项目启动画面 ② mybatisplus启动画面 ③若依项目启动画面 还有很多各式各样好看的启动画面,那么怎么定 ...

  2. 【Azure Developer】一个复制Redis Key到另一个Redis服务的工具(redis_copy_net8)

    介绍一个简单的工具,用于将Redis数据从一个redis端点复制到另一个redis端点,基于原始存储库转换为.NET 8:https://github.com/LuBu0505/redis-copy- ...

  3. [oeasy]python0092_homebrew_家酿俱乐部_比尔盖茨_保罗艾伦

    编码进化 个人电脑 intel 8080 的出现 让 人人都 可能有 一台计算机 Ed Robert 的 创业之路 从 售卖 diy 组装配件 到进军 计算器市场 计算器 毕竟不是 个人计算机 这计算 ...

  4. [MRCTF2020]Ezpop(反序列化)

    打开题目即可得源码 Welcome to index.php <?php //flag is in flag.php //WTF IS THIS? //Learn From https://ct ...

  5. 简单的字符串处理函数_C语言

    字符串数组 // Code file created by C Code Develop #include "stdio.h" #include "stdlib.h&qu ...

  6. html5 video标签 去掉边框黑线

    只需在样式中添加: mix-blend-mode: darken; 注意:IE和Edge浏览器不支持mix-blend-mode属性

  7. vue codemirror sql编辑器功能 可自定义提醒(关键字,库名,表名),高亮,主题

    工作中再一次需要开发sql编辑器,优化上篇文章内容 https://www.cnblogs.com/Lu-Lu/p/14388888.html 本次功能是tab页打开多个sql编辑器,效果图: 安装: ...

  8. RDD入门了解

    RDD即resilient distributed dataset 弹性分布式数据集,简单来说就是数据集,可以类比python的list dict:但是数据是分布式存储的,可用于分布式计算:可以存在内 ...

  9. 写写Redis十大类型GEO(地理空间)的常用命令

    又是一个用于处理sql性能的类型,这个类型的核心思想就是把三维的地球变成二维的坐标,再将二维的坐标换成一维的点块,最后将一维的点块转化成base32编码 类型就是zset, 在shell的启动命令后加 ...

  10. 【爬虫】Java爬取省市县行政区域统计数据

    前言 网上看了好几个Python爬虫来爬取省市县行政区域统计 官网除了省市县以外,还有区,街道,居委村委层级 https://zhuanlan.zhihu.com/p/512852193 所以自己用J ...