环境
系统:windows10
IDE:vs2005
创建
1.创建项目
打开vs,文件,新建项目,win32控制台应用程序,为项目起名

点击下一步,选择应用程序类型,dll,附加选项,空项目,点击完成

2.编辑代码
用于测试的库包括一个函数一个类,函数实现计算阶乘的功能,类里包含打印爱心形状功能的成员函数。
对头文件夹右键点击,添加,新建项,选择头文件

Microsoft 专用
dllexport 和 dllimport 存储类特性是 C 和 C++ 语言的 Microsoft 专用扩展。 可以使用它们从 DLL 中导出或向其中导入函数、数据和对象。
语法
dllexport是在这些类、函数以及数据的申明的时候使用。用他表明这些东西可以被外部函数使用,即(dllexport)是把 DLL中的相关代码(类,函数,数据)暴露出来为其他应用程序使用。使用了(dllexport)关键字,相当于声明了紧接在(dllexport)关键字后面的相关内容是可以为其他程序使用的。
dllimport是在外部程序需要使用DLL内相关内容时使用的关键字。当一个外部程序要使用DLL 内部代码(类,函数,全局变量)时,只需要在程序内部使用(dllimport)关键字声明需要使用的代码就可以了,即(dllimport)关键字是在外部程序需要使用DLL内部相关内容的时候才使用。(dllimport)作用是把DLL中的相关代码插入到应用程序中。
_declspec(dllexport)与_declspec(dllimport)是相互呼应,只有在DLL内部用dllexport作了声明,才能在外部函数中用dllimport导入相关代码。
对于动态链接库,类和函数的格式:
导出函数
导出类
在使用时,使用
编辑头文件,对函数和类进行声明
#pragma once
#ifdef LIBSASA_EXPORTS
#define LIBSASA_API __declspec(dllexport)
#else
#define LIBSASA_API __declspec(dllimport)
#endif
LIBSASA_API void print_l();
class LIBSASA_API CCC{
public:
CCC(char *,int);
void intro_self();
private:
char name[1024];
int age;
};
DLL 项目的新项目模板会将 PROJECTNAME_EXPORTS 添加到定义预处理器宏。 在此示例中,Visual Studio 在生成 libsasa DLL 项目时定义 LIBSASA_EXPORTS。
定义 LIBSASA_EXPORTS宏时,LIBSASA_API 宏会对函数声明设置 __declspec(dllexport) 修饰符。 此修饰符指示编译器和链接器从 DLL 导出函数或变量,以便其他应用程序可以使用它。 如果未定义 LIBSASA_EXPORTS(例如,当客户端应用程序包含头文件时),LIBSASA_API 会将 __declspec(dllimport) 修饰符应用于声明。 此修饰符可优化应用程序中函数或变量的导入
在源文件夹,添加一个cpp文件,实现所需的功能

#include"sasa.h"
#include "sasa.h"
#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;
void print_love(){
float y,x,a;
for(y=1.5f; y>-1.5f; y-=0.1f){
for (x=-1.5f; x<1.5f; x+=0.05f){
a = x*x + y*y - 1;
putchar(a*a*a - x*x*y*y*y <= 0.0f? '*':' ');
}
putchar('\n');
}
}
CCC::CCC(char *n,int a){
memset(name, 0, sizeof(name));
strcpy(name, n);
age = a;
}
void CCC::intro_self(){
cout<<"I am a "<<age<<" year old person and my name is "<<name<<endl;
}
在菜单栏上选择生成>生成解决方案
DLL 和相关编译器输出放在解决方案文件夹正下方的“Debug”文件夹中 。 如果创建发布版本,该输出会放置在“Release”文件夹中
打开项目文件夹下的debug目录
会发现已经生成了相应的动态库文件libsasa.dll

同时又生成了一个.lib文件。对于.lib文件,通常是windows静态链接库文件。
实际上,这里的.lib文件不是静态链接库文件。这个.lib文件里有相应的.dll文件的名字和一个指明.dll文件中函数入口的顺序表。使用动态库编译程序时会使用到。因此,动态库的dll文件,伴随的lib文件和相关的头文件是一起发行的
使用
在msvc中,对于动态库的使用,有两种方法,一种方法是动态加载,在程序运行过程中,使用LoadLibrary()、GetProcessAddress()和FreeLibrary()三个函数动态的对动态库进行加载和卸载,此方法在编译运行时只需要dll文件的支持即可
另一种方法是静态加载,静态加载不仅需要dll文件,在程序编译时也需要dll文件对应的lib文件,这个lib文件会记录动态库名称与函数入口,使程序开始运行时能够正确的对动态库文件进行载入并使用。
下面使用静态加载的办法
1.创建项目
另外启动vs。新建一个项目

点击完成

在项目目录新建include和lib两个文件夹,将libsasa库的头文件和lib文件分别放进去

对头文件文件夹右键,添加,现有项,选择动态库头文件,添加include文件夹下的头文件

点击项目,属性,链接器,常规,附加库目录。将libabc项目生成的lib文件所在的目录添加进去

点击输入,附加依赖项,添加生成的lib文件名称

2.代码
对源文件文件夹右键,添加,新建项,创建一个cpp源文件

编辑源文件,调用动态库中相关功能
main.cpp
#include"include/sasa.h"
#include<windows.h>
#include<iostream>
int main(){
print_l();
CCC c("sks",55);
c.intro_self();
system("pause");
return 0;
}
点击启动调试,生成程序,之后会发现无法运行,因为系统找不到动态库libabc.dll

将动态库libsasa.dll拷贝到此文件夹下(系统会从程序运行目录下搜索动态库文件)

之后再次运行程序

为了使程序实现C++代码调用C语言代码,使用extern "C"进行修饰符号,因此动态库头文件的形式是
#pragma once
#ifdef LIBSASA_EXPORTS
#define LIBSASA_API __declspec(dllexport)
#else
#define LIBSASA_API __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C" {
#endif
LIBSASA_API void print_l();
class LIBSASA_API CCC{
public:
CCC(char *,int);
void intro_self();
private:
char name[1024];
int age;
};
#ifdef __cplusplus
}
#endif