在c++中实现反射的初步想法

最近在思考如何在c++中实现反射。事情的起因是这样的:我们服务器是用c++开发的,如果需要写一些测试用的GM指令的话,需要编写完GM代码后重新编译并且重启进程,工序繁琐且比较耗时。因此就有了想用脚本(lua或py)来写GM的想法。用脚本来做这事我觉得还挺适合的。首先可以免去编译、重启(通过脚本的reload)的过程。其次测试用的GM没有高性能的需求,并且一般在进行自测的阶段时,代码往往是频繁改动的,刚好适合用灵活的脚本:P

接下来的问题就是,要如何在项目中引入脚本。考虑到使用场景,我觉得这个脚本机制最核心的一点就是:不需要显示的定义出c++暴露给脚本的接口。因为这块主要是在测试环境下工作,因此主要关注的是使用更便捷。如果每一个c++模块都需要再手动写一个wrapper类才能用脚本调用它,这样就太繁琐了,完全背离了减负的初衷。

首先我想到的是自动生成wrapper类的代码,比如说使用SWIG。方法可以是把需要生成wrapper的模块(实际上c++没有模块,只有编译单元)的文件名集中写在一个文件,在编译构建时扫描文件中记录的模块,统一生成wrapper类。但这样其实并没有做到业务代码完全无感知,只是把写wrapper类的工作优化成写模块名:-(

那么扫描项目中的所有模块呢?不管是否需要,统统都生成一份wrapper。这似乎可行。不过我先不考虑它,因为我心里还有另外一个方法。

在前一个项目中,我了解到了一种通过反射来在c#中嵌入cpython虚拟机的方法。因此我在想,如果能在c++中实现一个反射,那不就可以做到用脚本调用c++代码了吗。

要在c++实现反射,不可避免的是要把一个模块(编译单元)的入口记录下来。其中入口包括了函数、全局变量、类的类型信息等等。一般的做法可能是显示的定义出一个模块的入口。优雅一点的可能是在.h文件里稍动手脚,悄悄的把入口信息记录下来。

但是我更希望是,在实现反射时能对原有代码做尽可能少的改动。并且最好可以和业务代码完全的分离。在线上环境下,能够不产生任何性能开销。因此,我想到了是另外一种方法。

实际上在编译的过程中,是有模块的入口信息的(比如说符号表)。但是在编译完之后,这些信息就被丢掉了。如果把这些编译的中间信息存下来,存成一个单独的文件,那么在运行时就可以在通过在文件中查找对应的信息,来实现反射了。类似于在调试时通过载入可执行文件对应的pdb,来获取调试信息一样。

原文地址:https://www.cnblogs.com/adinosaur/p/9693930.html

时间: 2024-10-17 06:27:45

在c++中实现反射的初步想法的相关文章

.Net 中的反射(序章) - Part.1

引言 反射是.Net提供给我们的一件强力武器,尽管大多数情况下我们不常用到反射,尽管我们可能也不需要精通它,但对反射的使用作以初步了解在日后的开发中或许会有所帮助. 反射是一个庞大的话题,牵扯到的知识点也很多,包括程序集.自定义特性.泛型等,想要完全掌握它非常不易.本文仅仅对反射做一个概要介绍,关于它更精深的内容,需要在实践中逐渐掌握.本文将分为下面几个部分介绍.Net中的反射: 序章,我将通过一个例子来引出反射,获得对反射的第一印象. 反射初步.Type类.反射普通类型.(修改中,近期发布..

[C#.NET] C#中使用反射的性能分析

最近在研究一个可配置系统的框架,在代码中大量使用了反射的方法,虽然借鉴到其他的语言,如java中反射性能都比较差,但是想到c#既然是一种强类型的语言,对于AppDomain中的类的调用应该性能不会差很多.   今天在mvp站点上看到有人说反射的性能很差,要避免使用,就写了一个简单的例子测试了一下   测试类如下:   namespace ReflectionTest.Test   {    public class CTester    {    public CTester()    {   

java中利用反射机制绕开编译器对泛型的类型限制

首先看下面这个例子 public static void main(String[] args) { ArrayList<Integer> al1 = new ArrayList<Integer>(); al1.add(1); ArrayList<String> al2 = new ArrayList<String>(); al2.add("hello"); //int型链表和string型链表,结果为true System.out.pr

Java中的反射——(1)什么是反射

Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class. public class ReflectTest { public static void main(String[] args) throws ClassNotFoundException { String str1 = "abc"; Class cls1 = String.class; Class cls2 = str1.getClass(); Class cls3 = Class.forNa

Android中通过反射来设置显示时间

这个Toast的显示在Android中的用途还是很大的,同时我们也知道toast显示的时间是不可控的,我们只能修改他的显示样式和显示的位置,虽然他提供了一个显示时间的设置方法,但是那是没有效果的(后面会说到),他有两个静态的常量Toast.SHORT和Toast.LONG,这个在后面我会在源码中看到这个两个时间其实是2.5s和3s.那么我们如果真想控制toast的显示时间该怎么办呢?真的是无计可施了吗?天无绝人之路,而且Linux之父曾经说过:遇到问题就去看那个操蛋的源代码吧!!下面就从源代码开

转载:JAVA中的反射机制

反射,当时经常听他们说,自己也看过一些资料,也可能在设计模式中使用过,但是感觉对它没有一个较深入的了解,这次重新学习了一下,感觉还行吧! 一,先看一下反射的概念: 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义. 反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接.但是反射使用不当会成本很高! 看概念很晕的,继续往下看. 二,反射机制的作用:

详解C#中的反射

反射(Reflection) 2008年01月02日 星期三 11:21 两个现实中的例子:1.B超:大家体检的时候大概都做过B超吧,B超可以透过肚皮探测到你内脏的生理情况.这是如何做到的呢?B超是B型超声波,它可以透过肚皮通过向你体内发射B型超声波,当超声波遇到内脏壁的时候就会产生一定的“回音”反射,然后把“回音”进行处理就可以显示出内脏的情况了(我不是医生也不是声学专家,不知说得是否准确^_^).2.地球内部结构:地球的内部结构大体可以分为三层:地壳.地幔和地核.地壳是固体,地核是液体,地幔

Android中Java反射技术的使用示例

import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import android.os.Bundle; import android.app.Activity; /** * Demo描述: * Android中Java反射技术的使用示例 * 在Java中描述字节码文件(xxx.class)的类叫Class * 反射的过程可视为剖析Class的过

python中的反射

在绝大多数语言中,都有反射机制的存在.从作用上来讲,反射是为了增加程序的动态描述能力.通俗一些,就是可以让用户参与代码执行的决定权.在程序编写的时候,我们会写很多类,类中又有自己的函数,对象等等.这些类和函数都是为了后序代码服务,程序员决定什么时候用到哪一个类,什么时候调用某个函数.但很多时候,我们需要根据用户的需求来决定执行哪一段代码块.用户可能是通过点击,输入数据,或者其他方式发出指令,反射则将用户的指令传递到需要执行的那一段代码块.这个过程是自动执行的,无需人工去核对用户指令是否应该执行那