windows下C++的反射功能

概述

c/c++如果在日志中查看某个结构体/类的每个变量名,变量值信息,只能通过printf逐个格式化,非常繁琐,如何做到类似protobuff转json的序列化功能呢?该dll库先通过分析pdb文件获取结构体/类的变量名称、变量地址,并序列化成完整json字符串,极大降低了开发者工作量。

详细

概述

通过pdb文件查找指定结构体的变量命名和变量地址,将指定的结构体变量内容序列话为json格式。

实现原理

com组件查找pdb文件

使用visual studio 编译后的c/c++工程在输出目录都会输出xxx.pdb文件,该pdb文件中包含了工程中类型的符号文件,在软件调试过程中非常重要。pdb文件格式的解析依赖com组件msdia120.dll,在成功注册msdia120.dll组件后,通过提供的方法对pdb文件进行解析:

    HRESULT hr = ::CoInitialize(NULL);{CComPtr<IDiaDataSource> pDiaDataSource;CComPtr<IDiaSession> pDiaSession;CComPtr<IDiaSymbol> pGlobalSymbol;CComBSTR bstrFilename = pdb_path;if (LoadDataFromPdb(bstrFilename, pDiaDataSource, pDiaSession, pGlobalSymbol)) {LoadAllUDTs(pGlobalSymbol);//解析所有数据类型,保存在全局变量g_map_udt中LoadAllEnums(pGlobalSymbol);ret = 1;}}::CoUninitialize();

对变量进行序列化

    #define TCDUMP(ref_var)            \tcDump(typeid(ref_var).name(), &(ref_var))

通过输入变量地址,通过关键字typeid获取变量类型,按照不同的变量类型进行不同方式的处理,比如已内置变量类型为列

    if (dump_as_builtin(type, ptr, root)) {return true;}
    bool dump_inv_as_builtin(const std::string& type, void* ptr, const Json::Value& root) {static const char* buildin_signed[] = {"char","wchar_t","signed char","int","short","long","__int8","__int16","__int32","__int64",};static const char* buildin_unsigned[] = {"unsigned char","unsigned short","unsigned int","unsigned long","unsigned __int8","unsigned __int16","unsigned __int32","unsigned __int64"};if (type == "bool") {*(bool*)ptr = root.asBool();return true;}if (type == "float") {*(float*)ptr = root.asFloat();return true;}if (type == "double") {*(double*)ptr = root.asDouble();return true;}for (auto t : buildin_signed) {if (type == t) {switch (type_size(type)){case 1:*(int8_t*)ptr = root.asInt();return true;case 2:*(int16_t*)ptr = root.asInt();return true;case 4:*(int32_t*)ptr = root.asInt();return true;case 8:*(int64_t*)ptr = root.asInt64();return true;default:return false;}}}for (auto t : buildin_unsigned) {if (type == t) {switch (type_size(type)){case 1:*(uint8_t*)ptr = root.asUInt();return true;case 2:*(uint16_t*)ptr = root.asUInt();return true;case 4:*(uint32_t*)ptr = root.asUInt();return true;case 8:*(uint64_t*)ptr = root.asUInt64();return true;default:return false;}}}return false;}

demo效果:

在release下执行tcdumpTest.exe 看效果

注意:使用前先看‘使用说明.txt’,需要先注册\DIA SDK\bin\msdia120.dll。

定义类、结构体:
    Class Ctest{Public:Int M_i = 1;Float M_f = 0.1;Double M_d = 0.2;Char M_c = 'a';Std::String M_str = "Hello World";Std::Vector<Int> M_v;Std::Map<Int, Std::String> M_map;};
赋值:
    Ctest Test;Test.M_v.Push_back(1);Test.M_v.Push_back(2);Test.M_v.Push_back(3);Test.M_map.Insert({ 1,"hello" });test.m_map.insert({ 2,"world" });
初始化tcDump,并序列化对象
    int ret = TCDUMP_INIT(R"(..\tcDumpTest.pdb)");if (ret == 0) {std::cout << "load pdb failed !!!" << std::endl;return 0;}// 打印 test 变量内容,已json格式输出auto retJson = TCDUMP(test);if (NULL == retJson) {return false;}std::cout << retJson << std::endl;
序列化结果retJson输出

结果输出

附加接口

能够通过已知结构体大小返回大小一致的结构体名称

 
  1. // 打印pdb中大小为 n的类和结构体名称
  2. std::cout << tcDump_GetSizeClass(sizeof(CTest)) << std::endl;
  3. 输出:---{ CTest }---

工程目录

-tcdump
-tcdumpTest

tcdump为dll工程,核心代码实现。
tcpdumpTest为测试工程。

注意点:

1、本工程基于windows,不支持linux
2、本工程默认支持vs2019,其他版本可以自行编译。
3、使用vs2019编译时,会提示map _Node 错误,只需把xtree文件中对应的 _Node 从protected修改为public,并重新编译即可
4、使用前先看‘使用说明.txt’,需要先注册\DIA SDK\bin\msdia120.dll。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/80437.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue3将页面导出成PDF文件(完美解决图片、表格内容分割问题)

vue3将页面导出成PDF文件&#xff08;完美解决图片、表格内容分割问题&#xff09; 1、安装依赖2、在utils中创建htmlToPDF.js文件3、在vue中引入并使用 1、安装依赖 npm install --save html2canvas // 页面转图片 npm install jspdf --save // 图片转pdf2、在utils中创建h…

数据驱动成功:小程序积分商城的数据分析

在当今数字化时代&#xff0c;数据被认为是企业成功的关键。小程序积分商城是一种流行的营销工具&#xff0c;可帮助企业吸引和留住客户&#xff0c;并提供有关客户行为和偏好的宝贵数据。本文将深入探讨如何通过数据分析实现小程序积分商城的成功&#xff0c;包括数据的收集、…

Linux内核 6.6版本将遏制NVIDIA驱动的不正当行为

Linux 内核开发团队日前宣布&#xff0c;即将发布的 Linux 6.6 版本将增强内核模块机制&#xff0c;以更好地防御 NVIDIA 闭源驱动的不正当行为。 Linux 内核开发团队日前宣布&#xff0c;即将发布的 Linux 6.6 版本将增强内核模块机制&#xff0c;以更好地防御 NVIDIA 闭源驱…

linux shell操作- 02 常用命令及案例

文章目录 常用命令 续 常用命令 续 定时任务 通过文本编辑cron任务&#xff0c;实现定时操作 分 小时 天 月 星期 绝对路径sh or cmd* 表示每个xxx&#xff0c;如每个小时每小时的第三分钟执行cmd-> 03 * * * * /home/lauf/scraw.sh每天的第5、8个小时执行-> 00 5,8 * *…

Golang反射相关知识总结

1. Golang反射概述 Go语言的反射&#xff08;reflection&#xff09;是指在运行时动态地获取类型信息和操作对象的能力。在Go语言中&#xff0c;每个值都是一个接口类型&#xff0c;这个接口类型包含了这个值的类型信息和值的数据&#xff0c;因此&#xff0c;通过反射&#x…

C/C++—Inline关键词

1、引入 inline 关键字的原因 在 c/c 中&#xff0c;为了解决一些频繁调用的小函数大量消耗栈空间&#xff08;栈内存&#xff09;的问题&#xff0c;特别的引入了 inline 修饰符&#xff0c;表示为内联函数。 在系统下&#xff0c;栈空间是有限的&#xff0c;假如频繁大量的…

大二上学期学习计划

这个学期主要学习的技术有SpringBoot&#xff0c;Vue&#xff0c;MybatisPlus&#xff0c;redis&#xff0c;还有要坚持刷题&#xff0c;算法不能落下&#xff0c;要坚持一天至少刷2道题目&#xff0c;如果没有布置任务就刷洛谷上面的&#xff0c;有任务的话就尽量完成任务&…

win11 Windows hello录入指纹失败解决方法

刚换了xps&#xff0c;启用了administrator账号&#xff0c;win11专业版&#xff0c;发现使用Windows hello录入指纹时&#xff0c;只要一录指纹就立即出错 尝试卸载重装设备驱动--无效 把Windows update更新到最新--无效 最后查到&#xff0c;是Windows对administrator账户进…

在MuJoCo环境下详细实现PPO算法与Hopper-v2应用教程: 深度学习强化学习实战指南

第一部分:简介与MuJoCo环境的配置 1.简介 强化学习已经在许多任务中展现了其强大的能力,从简单的游戏到复杂的机器人控制。今天,我们将集中讨论PPO(Proximal Policy Optimization)算法,一个已经被证明在多种任务中具有卓越性能的强化学习算法。特别地,我们将在MuJoCo模…

【React】React入门

目录 一、何为React二、React与传统MVC的关系三、React的特性1、声明式编程①、实现标记地图 2、高效灵活3、组件式开发(Component)①、函数式组件②、类组件&#xff08;有状态组件&#xff09;③、一个组件该有的特点 4、单向式响应的数据流 四、虚拟DOM1、传统DOM更新①、举…

配置Swagger开发环境有效,生产环境无效

安全扫描&#xff1a;通用信息泄漏【未授权访问ip:端口号/swagger-ui.html】 步骤一&#xff1a;配置启用变量【开发环境可用生产环境不可用】 application-dev.yml: swagger:enable: true application-pro.yml: swagger:enable: false 步骤二&#xff1a;根据配置变量控…

three3D的vite+vue版本基础代码

自己稍微处理一下目录结构 <script setup>// 导入three.js import * as THREE from three// 创建场景 const scene new THREE.Scene();// 创建相机 const camera new THREE.PerspectiveCamera(45, //视角window.innerWidth / window.innerHeight, //宽高比0.1, // 近平…

Ajax fetch navigator.sendBeacon 三个的区别

Ajax、fetch 和 navigator.sendBeacon 是用于发送网络请求的不同方法。 Ajax: Ajax 是一种传统的用于发送异步请求的技术。它使用 XMLHttpRequest 对象来发送数据和接收响应。通过创建 XMLHttpRequest 对象&#xff0c;你可以通过调用其 open() 方法指定请求的类型和 URL&#…

【YOLOV5】YOLOV5添加OTA

当前YOLOV5版本为7.0 第一步 在utils/loss.py添加ComputeLossOTA import torch.nn.functional as F from utils.metrics import box_iou from utils.torch_utils import de_parallel from utils.general import xywh2xyxyclass ComputeLossOTA:# Compute lossesdef __init__(…

Android开源 日志框架 LogDog V2.3.1

目录 一、简介 二、下载使用 添加jitpack 仓库 添加依赖: 三、更改 1、 LogDogV2.3.1初始化: 2、通过上面的初始化 &#xff0c;已经知道IJsonEngine 优化了泛型参数&#xff0c;采用 Object/Any 3、优化空异常的判断&#xff0c;哪怕打印变量是NULL LogDog会打印“nul…

05-Flask-Flask查询路由方式

Flask查询路由方式 前言命令行方式代码实现返回所有路由 前言 本篇来学习下Flask中查询路由的方式 命令行方式 # window 用set linux 用 export set FLASK_APPtest_6_flask运行发方式# 打印所有路由 flask routes代码实现返回所有路由 # -*- coding: utf-8 -*- # Time …

ElementPlus·面包屑导航实现

面包屑导航 使用vue3中的UI框架elementPlus的 <el-breadcrumb> 实现面包屑导航 <template><!-- 面包屑 --><div class"bread-container" ><el-breadcrumb separator">"><el-breadcrumb-item :to"{ path:/ }&quo…

Docker相关命令

Docker的官网下载docker&#xff0c;按照说明进行安装。 下载Nacos镜像&#xff1a;docker pull nacos/nacos-server 运行以下命令来启动Nacos容器&#xff1a;docker run --name nacos -e MODEstandalone -p 8848:8848 -d nacos/nacos-server 会创建一个名为"nacos"…

基于FPGA点阵显示屏设计-毕设

本设计是一1616点阵LED电子显示屏的设计。整机以EP2C5T144C8N为主控芯片,介绍了以它为控制系统的LED点阵电子显示屏的动态设计和开发过程。通过该芯片控制一个行驱动器74HC154和两个列驱动器74HC595来驱动显示屏显示。该电子显示屏可以显示各种文字或单色图像,采用4块8 x 8点…

目标检测YOLO实战应用案例100讲-基于锐化注意力的快速目标检测算法及其在遥感场景下的应用研究(下)

目录 3.3.2 最优锐化滤波方法的选择实验 3.3.3 最优池化提取方法的选择实验 3