编程实战:类C语法的编译型脚本解释器(四)总入口和使用方法

news2024/10/6 18:29:20

初级代码游戏的专栏介绍与文章目录-CSDN博客

我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。

这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。


系列入口:

           编程实战:类C语法的编译型脚本解释器(系列)-CSDN博客

        本文介绍总入口和使用方法。

目录

一、总入口

1.1 接口类

1.2 AttachScript连接到已编译的脚本

1.3 Compile编译

1.4 Execute执行

二、调用示例


一、总入口

1.1 接口类

	//脚本解释器接口
	class CZBScript;
	class IScript
	{
	private:
		CScript* m_p;
		string m_msg;
	public:
		IScript() :m_p(nullptr) {}
		string GetMessage()const;

		//连接
		bool AttachScript(CScript* p);

		//编译
		bool Compile(char const* _source, vector<pair<string, Variable > >* pEnvs = NULL);

		//执行
		string const& GetSource()const;
		bool IsCompiled()const;
		string& Report(string& ret)const;
		bool Execute(Variable& ret, vector<pair<string, Variable > >* pEnvs = NULL, void* pe = NULL);
		long GetExecCount()const;
	};

        这个入口是个壳,目的是减少客户代码需要包含的内容。CScript才是实际功能,IScript包含CSpript的指针,这样只需要一个前置声明,而不需要全部实现。

        接口化的另一个好处是模块界限很清晰,对外的都在这里,对内的不需要暴露。

1.2 AttachScript连接到已编译的脚本

        这个方法可能看起来很奇怪,其实呢,我的大部分代码都会考虑能否放在共享内存里面,节省时间和内存,所以这函数就是用来连接到共享内存里的已经编译好的数据结构的。

        保存到共享内存这部分应该是还不怎么满意的,暂时无视吧。

1.3 Compile编译

        编译需要用脚本和预设变量为参数。预设变量就是提前设置的变量,作为全局变量存在,和脚本内定义的变量一样用变量名访问。不过编译时并不需要实际有意义的值,只需要提供变量类型即可。当然了,如果插件里面对变量值也有要求当然是可以的。插件解释器编译时只检查类型,但插件的CheckPlugin做什么完全是用户决定的。

        巨汗!发现插件参数pc根本没法传,没这个参数,实现里面倒是有的

1.4 Execute执行

        执行需要提供预设变量和pe参数(pc参数还是没有,大BUG),预设变量参数按道理和编译时相比应该具有相同的变量名称和类型,如果有缺失或不一致,运行时可能会出错(运行时仍会检查数据类型的正确性)。

二、调用示例

//全局定义
CScript script;
IScript _script;
IScript * script=NULL;
string stlstr;
vector<pair<string,Variable > > envs;

//初始化,可以放在OnInitDialog
	script = &_script;
	if(NULL==zbscript)
	{
		MessageBox("内存不足","错误",MB_ICONSTOP);
		OnCancel();
	}
	script->AttachScript(&script);
	pair<string,Variable > tmppair;
	Variable tmpvar;
	tmpvar.type=Variable::LONG;
	tmppair.first="total";
	tmppair.second=tmpvar;
	envs.push_back(tmppair);

//编译
	CString str;

	m_Edit_Source.GetWindowText(str);
	if(script->GetSource()!=str.GetString() || !script->IsCompiled())
	{
		if(!script->Compile(str,&envs))
		{
			MessageBox(script->GetMessage().c_str(),"出错",MB_OK|MB_ICONSTOP);
		}
		m_Edit_Report.SetWindowText(script->Report(stlstr).c_str());
	}

//执行
	if(script->IsCompiled())
	{
		Variable var;
		envs[0].second=10L;
		if(!script->Execute(var,&envs))
		{
			MessageBox(script->GetMessage().c_str(),"出错",MB_OK|MB_ICONSTOP);
		}
		else
		{
			MessageBox(var.GetString().c_str(),"运行结果");
		}
		m_Edit_Report.SetWindowText(script->Report(stlstr).c_str());
	}

        上面的代码定义了预设变量“total”,类型为LONG,脚本里面是可以直接访问的,所有的内置函数也都是可以使用的。

        执行时的用户提供的指针pe没有传递,因为没有添加插件,用不到。

        添加插件的接口:

bool CPluginMap::AddPlugin(char const* name, Variable::types type, CPlugin* p);

        这是个静态方法,可以直接使用。

        运行结果:

        答案没问题吧? 


(这里是结束,但不是整个系列的结束)

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

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

相关文章

深入了解数据库设计中的规范化与反规范化

目录 零、前言 一、一些基本术语 二、关系模式 2.1. 什么是关系模式 2.2. 示例 三、数据依赖 3.1. 函数依赖 3.1.1. 完全函数依赖 3.1.2. 部分函数依赖 3.1.3. 传递函数依赖 3.2. 多值依赖 3.3. 连接依赖 四、规范化 4.1. 第一范式&#xff08;1NF&#xff09; …

Redis 性能管理

一、Redis 性能管理 #查看Redis内存使用 172.168.1.11:6379> info memory 1. 内存碎片率 操作系统分配的内存值 used_memory_rss 除以 Redis 使用的内存总量值 used_memory 计算得出。内存值 used_memory_rss 表示该进程所占物理内存的大小&#xff0c;即为操作系统分配给…

批量化处理和矩阵(torch)

左边是权重&#xff0c;右边是变量 高维可以看成二维的堆叠 总结&#xff1a;二维是一维的堆叠&#xff0c;三维是二维的堆叠。但似乎是为了引入矩阵&#xff0c;本来应该是左上角是第一组权重和第一组变量的乘积这种表示表示来着&#xff0c;最后成了和列向量乘积&#xff…

Python | Leetcode Python题解之第111题二叉树的最小深度

题目&#xff1a; 题解&#xff1a; class Solution:def minDepth(self, root: TreeNode) -> int:if not root:return 0que collections.deque([(root, 1)])while que:node, depth que.popleft()if not node.left and not node.right:return depthif node.left:que.appen…

认识K8s集群的声明式资源管理方法

前言 Kubernetes 集群的声明式资源管理方法是当今云原生领域中的核心概念之一&#xff0c;使得容器化应用程序的部署和管理变得更加高效和可靠。本文将认识了解 Kubernetes 中声明式管理的相关理念、实际应用以及优势。 目录 一、管理方法介绍 1. 概述 2. 语法格式 2.1 管…

猫头虎 解析:为什么AIGC在国内适合做TOB,在国外适合做TOC?

猫头虎 解析&#xff1a;为什么AIGC在国内适合做TOB&#xff0c;在国外适合做TOC&#xff1f; 博主 猫头虎 的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面…

掩码生成蒸馏——知识蒸馏

摘要 https://arxiv.org/pdf/2205.01529 知识蒸馏已成功应用于各种任务。当前的蒸馏算法通常通过模仿教师的输出来提高学生的性能。本文表明&#xff0c;教师还可以通过指导学生的特征恢复来提高学生的表示能力。从这一观点出发&#xff0c;我们提出了掩码生成蒸馏&#xff08…

《图解支付系统设计与实现》电子书_V20240525

相较于上次公开发布的V20240503版本&#xff0c;变更内容如下&#xff1a; 根据掘金网友zz67373&#xff08;李浩铭&#xff09;的勘误建议&#xff0c;优化了部分描述。增加&#xff1a;金额处理规范&#xff0c;低代码报文网关实现完整代码&#xff0c;分布式流控等内容。扩…

Golang | Leetcode Golang题解之第111题二叉树的最小深度

题目&#xff1a; 题解&#xff1a; func minDepth(root *TreeNode) int {if root nil {return 0}queue : []*TreeNode{}count : []int{}queue append(queue, root)count append(count, 1)for i : 0; i < len(queue); i {node : queue[i]depth : count[i]if node.Left …

(十一)统计学基础练习题五(50道选择题)

本文整理了统计学基础知识相关的练习题&#xff0c;共50道&#xff0c;适用于想巩固统计学基础或备考的同学。来源&#xff1a;如荷学数据科学题库&#xff08;技术专项-统计学二&#xff09;。序号之前的题请看往期文章。 201&#xff09; 202&#xff09; 203&#xff09; 2…

LeetCode 第131场双周赛个人题解

100309. 求出出现两次数字的 XOR 值 原题链接 求出出现两次数字的 XOR 值 - 力扣 (LeetCode) 竞赛 思路分析 签到题&#xff0c;一次遍历 AC代码 class Solution:def duplicateNumbersXOR(self, nums: List[int]) -> int:cnt Counter(nums)res 0st set(nums)for x …

linux系统环境—基础开发工具

目录 1. yum工具&#xff0c;进行软件安装 示例&#xff1a;下载第一个软件 2. vim编辑器&#xff0c;学会vim的简单配置 vim的基本操作 vim末行模式命令集 插入模式与普通编辑器差不多。无命令集合 3. gcc/g编译器的使用&#xff0c;并了解其过程&#xff0c;原理 1预…

脚注:书籍的小秘密,躲藏在脚注间

脚注&#xff1a;书籍的小秘密&#xff0c;躲藏在脚注间 脚注是一种在文本中提供补充信息、引用出处或注解的方式&#xff0c;有助于读者更全面地理解文中内容&#xff0c;并为进一步研究提供参考和跳转点。 在一书本中&#xff0c;脚注是额外提供给读者的文字信息&#xff0…

java:static关键字用法

在静态方法中不能访问类的非静态成员变量和非静态方法&#xff0c; 因为非静态成员变量和非静态方法都必须依赖于具体的对象才能被调用。 从上面代码里看出&#xff1a; 1.静态方法不能调用非静态成员变量。静态方法test2()中调用非静态成员变量address&#xff0c;编译失败…

Java进阶学习笔记19——内部类

1、 内部类&#xff1a; 是类中五大成分之一&#xff08;成员变量、方法、构造函数、内部类、代码块&#xff09;&#xff0c;如果一个类定义在另一个 类的内部&#xff0c;这个类就是内部类。 场景&#xff1a;当一个类的内部&#xff0c;包含了一个完整的事物&#xff0c;且…

[笔试训练](三十三)097:跳台台阶扩展问题098:包含不超过两种字符的最长子串099:字符串的排列

目录 097:跳台台阶扩展问题 098:包含不超过两种字符的最长子串 099:字符串的排列 097:跳台台阶扩展问题 题目链接:跳台阶扩展问题_牛客题霸_牛客网 (nowcoder.com) 题目&#xff1a; 题解&#xff1a; 规律题: 1.跳上n级台阶的跳法等于前面1~(n-1)级台阶跳法的总和1。 2.跳…

[5] CUDA线程调用与存储器架构

CUDA线程调用与存储器架构 前几节简单讲了如何编写CUDA程序&#xff0c;利用GPU的处理能力并行执行多个线程和块。之前所有程序里的线程是相互独立的&#xff0c;没有多个线程之间的通信多是实际应用程序需要中间线程之间的通信&#xff0c;本文将仔细讲解线程调用以及CUDA的分…

Gradle的settings.gradle.kts你真的理解吗?

你还在用.gradle文件吗&#xff1f;例如build.gradle、settings.gradle&#xff0c;那么你就out了。现在我们有必要了解一下kts脚本了。在Android项目中&#xff0c;默认有3个文件可以替换成kts脚本&#xff0c;即project的build.gradle、app模块的build.gradle和project的sett…

关于在子线程中获取不到HttpServletRequest对象的问题

这篇文章主要分享一下项目里遇到的获取request对象为null的问题&#xff0c;具体是在登录的时候触发的邮箱提醒&#xff0c;获取客户端ip地址&#xff0c;然后通过ip地址定位获取定位信息&#xff0c;从而提示账号在哪里登录。 但是登录却发现获取request对象的时候报错了。 具…

数据插值之朗格朗日插值(一)

目录 一、引言 二、代码实现 2.1 Lagrange插值求插值多项式&#xff1a; 代码解析&#xff1a; 1.vpa解释 2.ploy&#xff08;x&#xff09;解释: 3.conv&#xff08;&#xff09;解释 4.poly2sym()解释 2.2 Lagrange插值求新样本值和误差估计&#xff1a; 代码解析&…