VS创建和加载动态库

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 
#include 

#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 
#include 

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)); //每隔1000ms通知一次
	}
}
7.生成解决方案,找到生成的dll,查看接口是否生成正确,打开vs工具命令提示符
8.cd到dll生成目录,运行dumpbin -exports MyDll.dll(对应的dll),红色框内就是生成的接口,至此dll生成完成。
9.示例程序说明:总共3个接口,其中2个接口用于外部调用,另外一个接口是回调,也就是将外部函数的地址作为参数传递进来,定义一个函数指针指向它,一有数据就调用它,然后就会调用外部函数,以实现回调,这样输入输出就都有了。

三、应用动态链接库

1.新建项目,win32控制台应用程序,点击:“下一步”,选择控制台应用程序,点击完成
2.在main.cpp里添加:
#include "stdafx.h"
#include 
#include 
#include 

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);

//dll回调
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");	//加载dll
	DWORD errorid = GetLastError();	//获取错误,返回0就是没有错误
	if (h_module)
	{
     
		//函数指针指向dll的函数名(函数的地址)
		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)
	{
     
		//调用dll接口
		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内部调用。

你可能感兴趣的:(C/C++,c++)