本文将详细介绍windows下如何制作.lib和.dll文件,并且还会介绍如果在项目中使用.lib和.dll文件。在进入正题之前,我们先来看看程序编译的四个过程。
从源文件到可执行文件中经历四个过程:
1.预编译:将原文件中头文件展开,宏定义处理(就是对宏定义进行替换)
2.汇编:对预编译处理好的.i文件进行语法检测,提示,生产.s文件,对其他错误不做检查(将高级语言翻译成汇编语言)
3.编译:对汇编处理好的.s文件进行编译,编译为机器能之间看得懂的语言(也就是0/1二进制)
4.链接:让调用函数和调用的目标文件与主目标文件链接,生成可执行文件。该过程会对没有进行定义而调用的函数进行报错
程序编译的链接环节有两种方式,分别是动态链接与静态链接。
静态连接库就是把 (lib) ⽂件中⽤到的函数代码 直接链接进⽬标程序 ,程序运⾏的时候不再需要其它的库⽂件。
动态链接通俗来讲就是随用随取,只有当程序运行是用到了所需要的模块,才会把dll文件加载进来,其好处就是当我们对dll文件进行替换,不需要重新编译整个程序,只需要更换dll文件即可。
首先我们在visual studio中新建一个空项目,之后添加两个文件test.h、test.cpp,项目整体如图所示:
之后在test.h中写入代码
#pragma once
#include
class myClass
{
public:
myClass();
void print();
};
test.cpp中写入代码
#include"test.h"
myClass::myClass()
{
}
void myClass::print()
{
printf("hello lib");
}
之后右键单击staticlib项目,选择属性,并将配置类型修改为静态库。
之后编译程序,如图所示则静态库生成成功。
新建项目libtest,并根据之前静态库生成的路径找到生成的静态库staticlib\x64\Debug\staticlib.lib以及staticlib\staticlib\test.h文件,并将其复制到libtest\lib文件夹中。
之后右键项目进入属性界面,选择C/C++ —> 常规 —>附加包含目录,将我们之前创建的lib文件夹加入路径。
之后再选择 链接器—>常规—>附加库目录,也是将lib文件加入其中。
最后进入 链接器–>输入—>附加依赖项,输入staticlib.lib
自此以后就可以再项目中使用我们之前封装过的lib文件里的myClass类了。
visual studio 新建dll项目
创建plugin.h文件
#pragma once
#include
#include
using namespace std;
//此处的作用是告诉程序被PLUGIN_API
//修饰的在dll文件中的变量会被外界调用
#ifdef DLL_EXPORTS
#define PLUGIN_API __declspec(dllexport)
#else
#define PLUGIN_API __declspec(dllimport)
#endif
class IPlugin
{
public:
IPlugin() = default;
virtual ~IPlugin() = default;
IPlugin(const IPlugin&) = delete;
IPlugin& operator=(const IPlugin&) = delete;
public:
virtual string getVersionString() const = 0;
//! \brief 获取业务名称
//! \return
virtual string getPluginName() const = 0;
//! \brief 执行业务的主要接口方法
//! \param msg 由外部程序发送的通讯协议(比如json报文)
//! \return 错误信息
virtual void exec(const string& msg) = 0;
//! \brief 业务停止运行
//! \return
virtual void stop() { return; }
//! \brief 释放动态库资源
//! \return 错误信息
virtual void release() = 0;
};
创建pluginTest.h文件
#pragma once
#include"plugin.h"
//用Test3继承IPlugin,并且在Test3中重写IPlugin中的纯虚函数,
//使得封装好的dll文件不会暴露内部具体实现的细节,只是对用户提供父类接口,
//在使用的时候通过外部调用getinstance()函数获取实例。
class Test3 : public IPlugin
{
public:
Test3();
virtual string getVersionString() const;
//! \brief 获取业务名称
//! \return
virtual string getPluginName() const;
public:
//! \brief 执行业务的主要接口方法
//! \param msg 由外部程序发送的通讯协议(比如json报文)
//! \return 错误信息
virtual void exec(const string& msg);
//! \brief 业务停止运行
//! \return
virtual void stop();
//! \brief 释放动态库资源
//! \return 错误信息
virtual void release();
};
//此处一定要加 extern "C" PLUGIN_API 修饰,
//不然后面会找不到dll文件中的信息
extern "C" PLUGIN_API void *getinstance();
创建pluginTest.cpp文件
#include "pluginTest.h"
void* getinstance()
{
return new Test3;
}
Test3::Test3()
{
}
string Test3::getVersionString() const
{
return "3.0\n";
}
string Test3::getPluginName() const
{
return "Test3\n";
}
void Test3::exec(const string& msg)
{
printf("execute command %s\n", msg.c_str());
}
void Test3::stop()
{
printf("program stop\n");
}
void Test3::release()
{
printf("release plugram\n");
}
接着在项目属性中,设置配置类型为动态库(.dll)
自此dll文件生成在了 ./x64/Debug目录下。
创建新项目pluginTest,同静态库一样,将动态库生成的plugin.dll文件和plugin.h文件放到/pluginTest/lib文件夹中
将plugin.h加入项目,并且在pluginTest.cpp中写入代码
// pluginTest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include
#include "windows.h"
#include"plugin.h"
using namespace std;
typedef void* (*obj)();
int main()
{
HINSTANCE hDLL; // Handle to DLL
obj instance; // Function pointer
//显示载入plugin.dll动态库
hDLL = LoadLibrary(L"C:\\Users\\99352\\Desktop\\test\\pluginTest\\dll\\plugin.dll");
if (NULL != hDLL)
{
//用函数指针捕获plugin.dll中的void *getinstance();函数
instance = (obj)GetProcAddress(hDLL, "getinstance");
if (NULL != instance)
{
IPlugin* plugin = (IPlugin*)instance();
plugin->exec("sas");
plugin->release();
plugin->stop();
cout << plugin->getPluginName() << endl;
cout << plugin->getVersionString() << endl;
}
else
{
// report the error
cout << "error" << endl;
}
FreeLibrary(hDLL);
}
int a;
cin >> a;
}
之后右键项目进入属性界面,选择C/C++ —> 常规 —>附加包含目录,将我们之前创建的lib文件夹加入路径。