官方下载地址:https://visualstudio.microsoft.com/zh-hans/
本专栏使用Win10 x64操作系统安装Visual Studio 2022
无论是用CANoe还是周立功软件,亦或是Diva自动化测试,都需要加载27服务的安全算法,存在一种载体能够动态修改且被调用的库文件,否则对于无序的安全种子来说,没有太多的手段去解决算法;同时它能够被代码调用、被Vector相关软件/Python等调用。因此dll被选择使用作为安全算法的载体。
.dll文件是Dynamic Link Library(动态链接库)文件的缩写,它是一种共享库文件,包含了程序所需的代码和数据。与静态链接库不同,动态链接库可以在程序运行时动态加载,使得程序的内存占用更小,同时也方便了程序的更新和维护。
DLL文件中存放的是各类程序的函数(子过程)实现过程,当程序需要调用函数时需要先载入DLL,然后取得函数的地址,最后进行调用。
诊断中的seedkey使用dll极为广泛,熟练的掌握DLL编程可以更快速的完成诊断测试。
生成(B)——生成解决方案
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#define MYDLL_EXPORTS
#include "function.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
MYDLL int my_function(int a, int b)
{
return (a + b);
}
#ifndef FUNCTION_H
#define FUNCTION_H
#if _MSC_VER > 1000
#pragma once
#endif
// C++ 常规编译写法
#ifdef MYDLL_EXPORTS
#define MYDLL extern "C" __declspec(dllexport)
#else
#define MYDLL __declspec(dllimport)
#endif
//声明自定义函数
MYDLL int my_function(int a, int b);
#endif
将第三步生成的DLL_Project.dll复制到此工程目录下
Ctrl + F5,查看输出结果
// Call_DLL.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include
#include
#include
int main()
{
HINSTANCE handle = LoadLibrary(_T("DLL_Project.dll"));
if (handle)
{
typedef int(*DLL_FUNCTION_ADD) (int, int); //typedef定义一下函数指针,(int, int) 是要调用dll中的函数参数类型
DLL_FUNCTION_ADD my_add = (DLL_FUNCTION_ADD)GetProcAddress(handle, "my_function");
if (my_add)
{
int result = my_add(43, 132);
std::cout << "my_add结算结果:" << result << "\n";
FreeLibrary(handle); //卸载句柄
}
}
return 0;
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门使用技巧:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件
// C++ 常规编译写法
#ifdef MYDLL_EXPORTS
#define MYDLL extern "C" __declspec(dllexport)
#else
#define MYDLL __declspec(dllimport)
#endif
可以使用 __declspec(dllexport) 关键字从 DLL 中导出数据、函数、类或类成员函数。 __declspec(dllexport) 将导出指令添加到对象文件中,因此你不需要使用 .def 文件。在DLL代码本身就是__declspec(dllexport) ,在使用DLL的程序中就变成了__declspec(dllimport),这两个标志分别用来指明当前的函数将被导出还是是被导入的。
如果调用模块和被调用模块都是C++(而且是同一种编程环境,如VC),那么就不需要extern “C”了,因为这个标志的作用就是用在函数和变量声明前,无论是调用模块,还是被调用模块,都将生成C的修饰符。调用模块需要C修饰符的函数,而被调用模块则生成C修饰符的函数,
所以这个标志在两者都是C++的时候使用并不受影响。但是如果C模块要调用C++ 模块,那么C++模块就需要使用extern “C”
VS生成的DLL是不能直接在CANoe中使用的,CANoe有自己的规则,大家可以结合后续博客理解。