【dll】windows下使用vs编译动态链接库dll与使用

一、需求

 编译出可供其他平台使用的基于c语言的函数库dll。

二、前言

 网上很多相关操作,但部分说明不详细或是没有配套的示意图导致操作遇到困难,且使用vs时会由于需要进行各种配置导致编译生成失败,因此才准备将每一步操作都记录下来,确保按照操作步骤能够顺利生成dll库。分为两部分,第一部分是工程创建,经过各种工程类型选择的测试,使用如下方法可减少更多的配置操作。第二部分是c代码编写,涉及到MicrosoftVC的一些关键字与声明的操作。

三、代码工程与项目操作

默认已安装且可正常使用visual stdio开发项目。

3.1新建项目

左上角标签卡,“文件”->“新建”->“项目”,如下图:

3.2使用向导新建

经试验多个项目类,其他类需要创建后进行配置,使用向导新建项目后可直接编译生成dll库。因此选择“Visual C++”->“Windows桌面”->"Windows桌面向导“,命名工程后确认生成,如下图:

 3.3选择应用程序类型

应用程序类型默认为”.exe“,此时需进入下拉选框选择”动态链接库(dll)“。然后勾选”空项目“确保新生成的工程中代码干净。如下图: 

3.4创建完成

此时工程相关操作已完成。

扫描二维码关注公众号,回复: 15498607 查看本文章

3.5平台切换

默认为x86平台,需切换到x64平台,否则生成的dll会造成不兼容导致无法准确读取的情况,配置如图:

四、c代码操作

文件创建与基本声明部分省略,源码会放到文章末尾的附录处。

4.1声明修饰

如需使用dll,在函数的外部声明处需使用”__declspec(dllexport)“和”__declspec(dllimport)“关键词进行修饰。

  • __declspec(dllexport):用于通过编译产生dll进行数据导出的函数
  • __declspec(dllimport):用于通过调用dll进行获取导入数据的函数

上述修饰一般在函数类型声明前,如下:

 4.2编译

编译成功后会在子目录下产生对应工程名称的dll文件,如下:

五、验证使用

验证需使用另外一个全新的项目,例如自带”hello world!“的 控制台应用。

5.1头文件声明

必备声明如下:

#include<Windows.h>//必备

 5.2读取dll文件

使用LoadLibrary函数读取,用HINSTANCE类型变量接收。

HINSTANCE hDll = LoadLibrary(_T("dll1.dll"));
if (hDll == NULL) {
	printf("lib not exist.");
	return 1;
}

 5.3定义函数类型

已知dll函数的声明类型与参数类型。

using functionPtrCreate = t_obj*(*)();
using functionPtrSetID = void(*)(t_obj*,long);
using functionPtrGetID = long(*)(t_obj*);

5.4GetProcAddress加载函数

functionPtrCreate objCreate = (functionPtrCreate)GetProcAddress(hDll, "objCreate");
functionPtrSetID objSetID = (functionPtrSetID)GetProcAddress(hDll, "objSetID");
functionPtrGetID objGetID = (functionPtrGetID)GetProcAddress(hDll, "objGetID");

5.5使用加载的函数输出结果

输入:

objSetID(temp, 10086);

 输出:

std::cout << objGetID(temp);

结果: 

附录 源码

1、dll_config_global.h

#ifndef _DLL_CONFIG_GLOBAL_H_
#define _DLL_CONFIG_GLOBAL_H_

/*逻辑分支,判断环境*/
#if defined(_MSC_VER) || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
#  define DLL_CONFIG_DECL_EXPORT __declspec(dllexport)//用于dll数据导出
#  define DLL_CONFIG_DECL_IMPORT __declspec(dllimport)//用于导入dll数据
#else
#  define DLL_CONFIG_DECL_EXPORT     __attribute__((visibility("default")))//失效
#  define DLL_CONFIG_DECL_IMPORT     __attribute__((visibility("default")))//失效
#endif

#endif // _DLL_CONFIG_GLOBAL_H_

 2、dll_demo.h

#ifndef _DLL_DEMO_H_
#define _DLL_DEMO_H_

/*dll编译需要使用的全局配置文件*/
#include "dll_config_global.h"

/*c库*/
#include<stdio.h>
#include<stdint.h>
#include<stdlib.h>
#include<stdbool.h>
#include<string.h>
#include<math.h>

/*结构体类声明*/
typedef struct _obj {
	bool En;//使能
	long ID;//id
	const char * name;//一般名称
	void * data;//数据包
} t_obj;//基本对象

/*函数外部声明*/
#ifdef _cplusplus
extern "C" {
#endif // _cplusplus{}

	DLL_CONFIG_DECL_EXPORT t_obj* objCreate();
	DLL_CONFIG_DECL_EXPORT void objEnable(t_obj*obj);
	DLL_CONFIG_DECL_EXPORT void objDisable(t_obj*obj);
	DLL_CONFIG_DECL_EXPORT bool objGetEn(t_obj*obj);
	DLL_CONFIG_DECL_EXPORT void objClearID(t_obj*obj);
	DLL_CONFIG_DECL_EXPORT void objSetID(t_obj*obj, long val);
	DLL_CONFIG_DECL_EXPORT long objGetID(t_obj*obj);
	DLL_CONFIG_DECL_EXPORT void objClearName(t_obj*obj);
	DLL_CONFIG_DECL_EXPORT void objSetName(t_obj*obj, char*val);
	DLL_CONFIG_DECL_EXPORT const char* objGetName(t_obj*obj);
	DLL_CONFIG_DECL_EXPORT void objClearData(t_obj*obj);
	DLL_CONFIG_DECL_EXPORT void objSetData(t_obj*obj, void*p, long length);
	DLL_CONFIG_DECL_EXPORT void* objGetData(t_obj*obj);

#ifdef _cplusplus

#endif // _cplusplus{}


#endif // _DLL_DEMO_H_

3、dll_demo.c

#include"dll_demo.h"

//----节0
/*创建基本对象*/
DLL_CONFIG_DECL_EXPORT t_obj* objCreate() {
	return (t_obj*)malloc(sizeof(t_obj));
}

//----节1
/*使能对象*/
DLL_CONFIG_DECL_EXPORT void objEnable(t_obj*obj)
{
	obj->En = true;
}
/*失能对象*/
DLL_CONFIG_DECL_EXPORT void objDisable(t_obj*obj)
{
	obj->En = false;
}
/*获取对象状态*/
DLL_CONFIG_DECL_EXPORT bool objGetEn(t_obj*obj)
{
	return obj->En;
}

//----节2
/*清空id*/
DLL_CONFIG_DECL_EXPORT void objClearID(t_obj*obj)
{
	obj->ID = 0x00;
}
/*设置id*/
DLL_CONFIG_DECL_EXPORT void objSetID(t_obj*obj,long val)
{
	obj->ID = val;
}
/*获取对象id*/
DLL_CONFIG_DECL_EXPORT long objGetID(t_obj*obj)
{
	return obj->ID;
}

//----节3
/*清空名称*/
DLL_CONFIG_DECL_EXPORT void objClearName(t_obj*obj)
{
	obj->name = NULL;
}
/*设置名称*/
DLL_CONFIG_DECL_EXPORT void objSetName(t_obj*obj,char*val)
{
	obj->name = val;
}
/*获取对象名称*/
DLL_CONFIG_DECL_EXPORT const char* objGetName(t_obj*obj)
{
	return obj->name;
}

//----节4
/*清空数据包*/
DLL_CONFIG_DECL_EXPORT void objClearData(t_obj*obj)
{
	free(obj->data);
	obj->data = NULL;
}
/*设置数据包*/
DLL_CONFIG_DECL_EXPORT void objSetData(t_obj*obj,void*p,long length)
{
	obj->data = malloc(length);
	memcpy(obj->data, p, length);
}
/*获取对象数据包*/
DLL_CONFIG_DECL_EXPORT void* objGetData(t_obj*obj)
{
	return obj->data;
}


4、dllUse.cpp

#include<iostream>
#include<Windows.h>//必备
#include<tchar.h>
//#pragma comment(lib,"dll1.lib")
typedef struct _obj {
	bool En;//使能
	long ID;//id
	const char * name;//一般名称
	void * data;//数据包
} t_obj;//基本对象

int main()
{
	HINSTANCE hDll = LoadLibrary(_T("dll1.dll"));
	if (hDll == NULL) {
		printf("lib not exist.");
		return 1;
	}
	using functionPtrCreate = t_obj*(*)();
	using functionPtrSetID = void(*)(t_obj*,long);
	using functionPtrGetID = long(*)(t_obj*);
	//找到所需要的函数
	
	functionPtrCreate objCreate = (functionPtrCreate)GetProcAddress(hDll, "objCreate");
	functionPtrSetID objSetID = (functionPtrSetID)GetProcAddress(hDll, "objSetID");
	functionPtrGetID objGetID = (functionPtrGetID)GetProcAddress(hDll, "objGetID");
	t_obj* temp = objCreate();
	objSetID(temp, 10086);
	std::cout << objGetID(temp);

}

猜你喜欢

转载自blog.csdn.net/qq_34217861/article/details/126537073
今日推荐