本文使用的是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. 解决方案 | tk.entry数字验证(输入框如何保证只能输入数字)

    from tkinter import * root = Tk() # 创建文本框 entry = Entry(root) entry.pack() # 设置文本框只能输入数字 entry.confi ...

  2. 网易数帆内核团队:memory cgroup 泄漏问题的分析与解决

    memory cgroup 泄露是 K8s(Kubernetes) 集群中普遍存在的问题,轻则导致节点内存资源紧张,重则导致节点无响应只能重启服务器恢复:大多数的开发人员会采用定期 drop cach ...

  3. 如何删除Git中缓存的用户名和密码

    昨天在上传代码的时候提示输入用户名密码,结果输错了3次就没有提示框了,就一直报错(身份验证失败),没办法提交代. 在使用git的过程中,我们也会经常遇到以前保存在git的用户名密码忘记了,或者不用了. ...

  4. [oeasy]python0074[专业选修]字节序_byte_order_struct_pack_大端序_小端序

    进制转化 回忆上次内容 上次 总结了 计算字符串值的函数 eval   四种进制的转化函数 bin oct int hex     函数名 前缀 目标字符串所用进制 bin 0b 二进制 oct 0o ...

  5. P2427 题解

    洛谷链接 题目简述 给定 \(N \times M\) 的字符矩阵,有 \(Q\) 次询问,对于每次询问给出 \(x,y\),求以 \((x,y)\) 为中心的最大正方形边长且正方形中字符均相同. 思 ...

  6. odoo 开发入门教程系列-一个新应用

    一个新应用 房地产广告模块 假设需要开发一个房地产模块,该模块覆盖未包含在标准模块集中特定业务领域. 以下为包含一些广告的主列表视图 form视图顶层区域概括了房产的重要信息,比如name,Prope ...

  7. Centos7下安装配置最新版本Jenkins(2.452.3)

    1.基础环境配置 1.1 服务器下载Jenkins安装包 下载地址:https://www.jenkins.io/download/ 下载命令:wget https://get.jenkins.io/ ...

  8. 关于mybatisplus与mybatis的自动填充混用问题

    public class MybatisPlusAutoFillHandler implements MetaObjectHandler { //插入时的填充策略 @Override public v ...

  9. RPA处理京东滑块拼图验证码

    在进行京东商家后台企业账号的RPA自动化操作过程中,登录环节是必不可少的步骤.然而,这一过程中有时会遇到一种特殊的验证机制--滑块拼图验证码,它的突然出现如同一道屏障,阻碍了自动化的顺利进行.因为只有 ...

  10. pyglet.gl.ContextException: Could not create GL context

    参考: https://www.saoniuhuo.com/question/detail-2725960.html ========================================= ...