Loadlibrary方式不在需要.lib库,当我们编译动态库的时候,会生成两个文件,.dll和.lib ,lib和静态库不同,只是有一些函符号,真正的实现在dll里。所以说,编译动态库时生成的lib是可以不需要的。但是,如果你不采用Loadlibrary的方式,那么两个文件都需要。
下面写了一个小例子:
1、编译库
我们先编译一个库文件,然后采用Loadlibrary的方式调用。
mydll.h
#pragma once
#include <windows.h>
#include <iostream>
using namespace std;
#define MY_DLL_EXPORTS
#ifdef MY_DLL_EXPORTS
#define MY_DLL_API __declspec(dllexport)
#else
#define MY_DLL_API __declspec(dllimport)
#endif
extern "C" MY_DLL_API int open_device(int handle);
extern "C" MY_DLL_API int open_seesion(int hseion);mydll.cpp
#include "mydll.h"
extern "C" MY_DLL_API int open_device(int handle)
{
cout << "display func: open_device,"<<"handle is:"<< handle << endl;
return 0;
}
extern "C" MY_DLL_API int open_seesion(int session)
{
cout << "display func: open_seesion,"<<"session is:"<< session << endl;
return 0;
}默认的调用方式为:
属性->C/C+±>高级-> 调用约定: __cdecl (/Gd)

编译完后,我们用dumpbin看一下导出符号:

说明库里边已经把函数导出来了,使用loadlibrary的时候需要和导出名字对应上。
2、编译调用app
注意,你的应用程序和库文件要在同一个目录下。
Loadlibrary_test.cpp
#include <iostream>
#include <Windows.h>
#include "mydll.h"
using namespace std;
int main(void)
{
HMODULE hMod = LoadLibrary(TEXT("lib_dll.dll"));//载入dll,TEXT为了兼容格式,防止报类型错误
if (hMod == nullptr)
{
cout << "load dll error!" << endl;
return -1;
}
typedef int(* Open_Device)(int);
typedef int(* Open_Seesion)(int);
Open_Device opendev = (Open_Device)GetProcAddress(hMod, "open_device");//获取函数地址
if (opendev == nullptr)
{
cout << "load open_device error!" << endl;
return -1;
}
int rv = opendev(1);//通过函数指针调用函数
Open_Seesion openses = (Open_Seesion)GetProcAddress(hMod, "open_seesion");
if (openses == nullptr)
{
cout << "load open_session error!" << endl;
return -1;
}
rv = openses(2);//通过函数指针调用函数
FreeLibrary(hMod);
system("pause");
return 0;
}现象:


3、备注
顺便再讲下关于调用约定和函数符号的关系,即_stdcall, _cdecl.还有就是extern "c"对函数名符号的影响。
extern “C” + _stdcall,函数导出符号为 : _+函数名+@+传参字节数
由于_stdcall是被调用方清理堆栈,所以函数符号里面包含了传参的信息
extern “C” + _cdecl,函数导出符号为 : 函数名
由于_cdecl是调用方清理堆栈,所以只需要函数名就可以
不使用extern的情况下,是C++的导出方式,函数符号如下:
:?+函数名+@@YG+返回类型+参数1类型…+@Z
如果是_cdecl @YG变为@YA
如果没有参数即参数为void,则以Z结尾,例如:
: ?+函数名+@@YA+返回类型+XZ
以上 X表示 void类型,H表示int参数类型
配置属性里边如果生成调试信息选否,到出库里就会只有函数名:


















