当前位置:网站首页>VS2015采用loadlibrary方式调用dll库
VS2015采用loadlibrary方式调用dll库
2022-07-29 09:05:00 【无聊的阿乐】
参考:
//blog.csdn.net/luoyu510183/article/details/93666808
//blog.csdn.net/SonnAdolf/article/details/80339070
//blog.csdn.net/blade1080/article/details/81538384
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;
}
默认的调用方式为:

编译完后,我们用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
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,函数导出符号为 : _+函数名[email protected]+传参字节数
由于_stdcall是被调用方清理堆栈,所以函数符号里面包含了传参的信息
extern “C” + _cdecl,函数导出符号为 : 函数名
由于_cdecl是调用方清理堆栈,所以只需要函数名就可以
不使用extern的情况下,是C++的导出方式,函数符号如下:
:?+函数名[email protected]@YG+返回类型+参数1类型…[email protected]
如果是_cdecl @YG变为@YA
如果没有参数即参数为void,则以Z结尾,例如:
: ?+函数名[email protected]@YA+返回类型+XZ
以上 X表示 void类型,H表示int参数类型
边栏推荐
- access数据库可以被远程访问吗
- Requests library simple method usage notes
- How does xjson implement four operations?
- How to change MySQL into Chinese
- Quick sorting (quick sorting) (implemented in C language)
- File upload and expansion
- Sublime text create page
- 2022 electrician (elementary) test question simulation test platform operation
- Parameter initialization
- (视频+图文)机器学习入门系列-第2章 线性回归
猜你喜欢
随机推荐
状态压缩dp
[C language] DataGridView binding data
Application of matrix transpose
Classic interview question: = = the difference between equals
What is the key to fast multi tag user profile analysis?
Want to know how to open an account through online stock? Excuse me, is it safe to open a stock account by mobile phone?
Multiple knapsack, simplicity and binary optimization
优秀的Allegro Skill推荐
Solve the problem of false Base64 character in Base64
C language -- 22 one dimensional array
How to quickly experience oneos
AxureRP原型设计 快速开始
Common query optimization technology of data Lake - "deepnova developer community"
(Video + graphic) introduction to machine learning series - Chapter 3 logical regression
Summary of some experiences in the process of R & D platform splitting
CVPR 2022 | clonedperson: building a large-scale virtual pedestrian data set of real wear and wear from a single photo
GBase 8s数据库有哪些备份恢复方式
2022年R2移动式压力容器充装考题模拟考试平台操作
Notes on network principles (five layer network)
Retinal Vessel Segmentation via a Semantics and Multi-Scale Aggregation Network









