文章目录
在编写应用软件时,代码重用是非常关键的一步,C++编程语言里,为了使编写的dll文件,能够实现重用,必须采取一些规则,否则不同编译器生成的dll,不用重用。首先在dll里编写的类必须导出。如下所示:
1.普通类导出
- 1.普通类导出
- 2.接口类导出
- 3.调用约定与参数命名
- 4.名字修饰约定
- 5.MFC导出宏
- 6.DLLMain函数
- 7.一个DLL在内存中只有一个实例
头文件:DLL_TEST_Export.H
#ifndef _DLL_TEST_H
#define _DLL_TEST_H
// 通过宏来控制是导入还是导出
#ifdef _DLL_TEST
#define DLL_TEST_API __declspec(dllexport)
#else
#define DLL_TEST_API __declspec(dllimport)
#endif
// 导出/导入变量声明
class DLL_TEST_API DLLClass
{
public:
void Show();
};
DLL_TEST_API float _stdcall Test(int i,bool j);
#endif
实现文件:DLL_TEST_Export.cpp
#include "stdafx.h"
#define _DLL_TEST
#include "DLL_TEST_Export.h"
#include "stdio.h"
//APIENTRY声明DLL函数入口点
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
void DLLClass::Show()
{
printf("DLLClass show!");
}
DLL_TEST_API float _stdcall Test(int i, bool j)
{
return 1.0;
}
调用文件:
#include "DLL_TEST_Export.h"
#pragma comment(lib,"DLLTest.lib")
int main(int argc, char *argv[])
{
DLLClass dc;
dc.Show();
return 0;
}
通过Dependency Walker可以看到,这时候的dll导出的是跟类相关的函数:如构造函数、赋值操作符、析构函数、其它函数,这些都是使用者可能会用到的函数。如下图所示: 这种简单导出类的方式,除了导出的东西太多、使用者对类的实现依赖太多以外,还有其他问题:必须保证使用同一种编译器。导出类的本质是导出类里的函数,因为语法上直接导出了类,没有对函数的调用方式、重命名进行设置,导致了产生的dll并不通用。
定义一个抽象类(都是纯虚函数),调用者跟dll共用一个抽象类的头文件,dll中实现此抽象类的派生类,dll最少只需要提供一个用于获取抽象类对象指针的接口。 这种方式利用了C++类的虚函数,类似COM思想,采用接口跟实现分离,可以使得工程的结构更清晰,使用者只需要知道接口,而无需知道具体实现,产生的DLL通用没有特定环境限制。调用者跟DLL共用一个抽象类的头文件,调用者依赖于DLL的东西很少,只需要知道抽象类的接口,以及获取对象指针的导出函数,对象内存空间的申请和释放都在DLL模块中完成。 func.h文件(接口文件):
#pragma once
#ifdef _DLL_EXPORTS
#define DLL_API _declspec(dllexport)
#else
#define DLL_API _declspec(dllimport)
#endif
class IAnimal
{
public:
virtual void eat() = 0;
virtual void sleep() = 0;
virtual void delObj() = 0;
};
extern "C" DLL_API IAnimal *GetCat();
func.cpp文件:
// DynamicLib.cpp: 定义 DLL 应用程序的导出函数。
//
#include "stdafx.h"
#define _DLL_EXPORTS
#include "func.h"
#include
using namespace std;
class Cat :public IAnimal
{
public:
Cat()
{
cout
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?