C++创建与调用dll动态链接库(MinGW64 Dev-C++)

C++创建与调用dll动态链接库(MinGW64 Dev-C++)

本文使用的是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

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

#include

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<

FreeLibrary(hMod);

return 0;

}

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

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

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

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

//dll.h

#include

#include

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

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

#include

#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到这里就结束了,欢迎大家指正:)

相关推荐

面包师傅薪资待遇
bat365官网登录下载

面包师傅薪资待遇

📅 06-27 👁️ 3612
世界各国男性平均长度排名(含70个国家)丨收藏
bat365官网登录下载

世界各国男性平均长度排名(含70个国家)丨收藏

📅 07-05 👁️ 7382
阴谋游戏有哪些 热门阴谋游戏排行
365bet官方网址

阴谋游戏有哪些 热门阴谋游戏排行

📅 07-03 👁️ 1732