VS创建和加载动态库
一、动态库使用的优点:
1.使资源数据独立于可执行程序之外,但又能较方便快速地访问它。
2.节省内存并减少页面交换。
3.大型软件开发,使开发过程独立、耦合度小,便于不同开发者和开发组织之间进行开发和测试。
4.保护自己的知识产权,与第三方合作时,只提供库,不用给源码。
......
二、创建动态链接库
1.打开VS:“文件”-“新建”-“项目”
2.打开:“已安装”-“模板”-“Visual C++”-“Win32”-“Win32 控制台应用程序”
把文件“名称”加上,为自己的工程名称;把“位置”加上,为自己的工程所在位置;
3.点击:“下一步”
4.选择“DLL”和“空项目”,然后点击“完成”
5.新建头文件和源文件,如:“MyDll.h”、“MyDll.cpp”:
6.在MyDll.h里添加:
#pragma once
#include <iostream>
#include <vector>
#define DLL_API __declspec(dllexport)
typedef void(*funCallBack)(std::vector<int> &_data);
extern "C" DLL_API void Dll_Void_Fun();
extern "C" DLL_API int Dll_Int_Fun(int a, int b);
funCallBack m_callBackFun = nullptr;
extern "C" DLL_API void Dll_CallBack_Fun(funCallBack pfunc);
void makeSimulateData();
void makeDataThread();
7.在MyDll.cpp里添加:
#include "MyDll.h"
#include <thread>
#include <mutex>
void Dll_Void_Fun()
{
std::cout << "void dll func called" << std::endl;
}
int Dll_Int_Fun(int a, int b)
{
std::cout << "int dll func called" << std::endl;
return a + b;
}
void Dll_CallBack_Fun(funCallBack pfunc)
{
m_callBackFun = pfunc;
makeSimulateData();
}
void makeSimulateData()
{
std::thread data_thread(makeDataThread);
data_thread.join();
}
void makeDataThread()
{
while (1)
{
std::vector<int> SimulateDataVector;
SimulateDataVector.push_back(0);
SimulateDataVector.push_back(1);
if(SimulateDataVector.size() != 0)
{
std::mutex m_mutex;
std::lock_guard<std::mutex> locker(m_mutex);
m_callBackFun(SimulateDataVector);
}
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
7.生成解决方案,找到生成的dll,查看接口是否生成正确,打开vs工具命令提示符
8.cd到dll生成目录,运行dumpbin -exports MyDll.dll(对应的dll),红色框内就是生成的接口,至此dll生成完成。
9.示例程序说明:总共3个接口,其中2个接口用于外部调用,另外一个接口是回调,也就是将外部函数的地址作为参数传递进来,定义一个函数指针指向它,一有数据就调用它,然后就会调用外部函数,以实现回调,这样输入输出就都有了。
三、应用动态链接库
1.新建项目,win32控制台应用程序,点击:“下一步”,选择控制台应用程序,点击完成
2.在main.cpp里添加:
#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include <vector>
typedef void(*func_void)();
typedef int(*func_int)(int a, int b);
typedef void(*funCallBack)(std::vector<int> &_data);
typedef void(*func_call_back)(funCallBack func);
void callBack(std::vector<int> &_data)
{
std::cout << "dll call back" << std::endl;
for (auto var : _data)
{
std::cout << var << std::endl;
}
}
int main()
{
func_void m_func_void = nullptr;
func_int m_func_int = nullptr;
func_call_back m_func_call_back = nullptr;
HMODULE h_module = LoadLibrary(L"MyDll.dll");
DWORD errorid = GetLastError();
if (h_module)
{
m_func_void = (func_void)GetProcAddress(h_module, "Dll_Void_Fun");
m_func_int = (func_int)GetProcAddress(h_module, "Dll_Int_Fun");
m_func_call_back = (func_call_back)GetProcAddress(h_module, "Dll_CallBack_Fun");
}
else
{
std::cout << "dll加载失败";
}
if (m_func_void&&m_func_int&&m_func_call_back)
{
m_func_void();
int sum = m_func_int(3, 4);
std::cout << "sum is " << sum;
m_func_call_back(callBack);
}
getchar();
return 0;
}
3.生成解决方案,运行。
四、动态链接库的调用与回调理解(自己理解的,仅供参考)
简单理解,调用就是将函数的地址暴露给外部程序,外部程序定义函数指针指定对应函数地址实现调用,
回调就是将函数的地址暴露给外部程序的同时,将外部程序的函数地址作为参数传递进来,定义函数指针
指向该地址,这样在调用时就会找到外部程序的地址调用外部程序,把需要传递的数据作为参数传递出去
实现回调。调用就是外部程序调用dll内的函数,回调是调用dll内的函数的同时将自身的某个函数地址作为
参数传递进去,让dll内部调用。
转载请注明原文地址:https://blackberry.8miu.com/read-15585.html