KRTSt内嵌Lua脚本

embedded/2024/10/21 23:34:00/

KRTStLua_0">KRTSt内嵌Lua脚本

Lua 简介

Lua是一门强大、高效、轻量、可嵌入的脚本语言。它支持多种编程架构:过程编程、面向对象编程(OOP)、函数式编程、数据驱动编程及数据描述。

Lua结合了简洁的过程语法和强大的数据描述结构(基于关联数组和可扩展语义)。Lua使用动态类型,运行时内部通过寄存器式虚拟机(register-based VM)来执行解释字节码,有自动内存管理和分代GC机制,是配置、编写脚本和原型设计的理想选择。

Lua是作为一个C语言编写的库实现的,其被标准C/C++所兼容。Lua的发行版本中包括一个独立程序(就叫 lua),它就是由Lua库所实现,作为一个完整独立的编译/解释器,也可以用于交互式使用或批量执行。Lua志在成为一门强大轻量可嵌入在任何需要的地方的脚本语言,并且是强力但轻便高效的独立语言。

作为扩展语言,Lua没有 主程序 的概念,它通常是 嵌入 到宿主程序中使用,宿主程序也被称为 被嵌入程序 或简称 宿主 (通常宿主程序指上边说到的独立程序lua)。宿主程序可以调用函数来执行一段Lua代码,可以写入或读取Lua变量,也可以注册C函数供Lua代码调用。通过使用C函数,可以在相同的语法框架下来自定义编程语言,从而使得Lua能够应用于广泛的领域。

Lua官网
Lua中文参考手册

功能简介

KRTS内核中内嵌Lua解释器和编译器执行Lua脚本您需要了解KRTS任务处理的相关知识,我们假设您已经学习了相关知识。本实例主要实现的功能是内核成调用Lua脚本执行和Lua脚本调用内核函数并运行;

在这里插入图片描述

工程构建

  • 构建KRTS任务程序(请查阅KRTS任务)

  • 下载Lua源码解压并加入项目中 (Lua 5.4.7源码)

  • 在这里插入图片描述

  • 移植Lua程序,将lua源码文件除了lua.c和luac.c之外,加入到内核工程即可,我是用CMake构建的项目,下面是简单的示例

set(LUA_LIST../3rdparty/lua-5.4.7/lapi.c../3rdparty/lua-5.4.7/lapi.h../3rdparty/lua-5.4.7/lauxlib.c../3rdparty/lua-5.4.7/lauxlib.h../3rdparty/lua-5.4.7/lbaselib.c../3rdparty/lua-5.4.7/lcode.c../3rdparty/lua-5.4.7/lcode.h../3rdparty/lua-5.4.7/lcorolib.c../3rdparty/lua-5.4.7/lctype.c../3rdparty/lua-5.4.7/lctype.h../3rdparty/lua-5.4.7/ldblib.c../3rdparty/lua-5.4.7/ldebug.c../3rdparty/lua-5.4.7/ldebug.h../3rdparty/lua-5.4.7/ldo.c../3rdparty/lua-5.4.7/ldo.h../3rdparty/lua-5.4.7/ldump.c../3rdparty/lua-5.4.7/lfunc.c../3rdparty/lua-5.4.7/lfunc.h../3rdparty/lua-5.4.7/lgc.c../3rdparty/lua-5.4.7/lgc.h../3rdparty/lua-5.4.7/linit.c../3rdparty/lua-5.4.7/liolib.c../3rdparty/lua-5.4.7/ljumptab.h../3rdparty/lua-5.4.7/llex.c../3rdparty/lua-5.4.7/llex.h../3rdparty/lua-5.4.7/llimits.h../3rdparty/lua-5.4.7/lmathlib.c../3rdparty/lua-5.4.7/lmem.c../3rdparty/lua-5.4.7/lmem.h../3rdparty/lua-5.4.7/loadlib.c../3rdparty/lua-5.4.7/lobject.c../3rdparty/lua-5.4.7/lobject.h../3rdparty/lua-5.4.7/lopcodes.c../3rdparty/lua-5.4.7/lopcodes.h../3rdparty/lua-5.4.7/lopnames.h../3rdparty/lua-5.4.7/loslib.c../3rdparty/lua-5.4.7/lparser.c../3rdparty/lua-5.4.7/lparser.h../3rdparty/lua-5.4.7/lprefix.h../3rdparty/lua-5.4.7/lstate.c../3rdparty/lua-5.4.7/lstate.h../3rdparty/lua-5.4.7/lstring.c../3rdparty/lua-5.4.7/lstring.h../3rdparty/lua-5.4.7/lstrlib.c../3rdparty/lua-5.4.7/ltable.c../3rdparty/lua-5.4.7/ltable.h../3rdparty/lua-5.4.7/ltablib.c../3rdparty/lua-5.4.7/ltm.c../3rdparty/lua-5.4.7/ltm.h#../3rdparty/lua-5.4.7/lua.c../3rdparty/lua-5.4.7/lua.h../3rdparty/lua-5.4.7/lua.hpp#../3rdparty/lua-5.4.7/luac.c../3rdparty/lua-5.4.7/luaconf.h../3rdparty/lua-5.4.7/lualib.h../3rdparty/lua-5.4.7/lundump.c../3rdparty/lua-5.4.7/lundump.h../3rdparty/lua-5.4.7/lutf8lib.c../3rdparty/lua-5.4.7/lvm.c../3rdparty/lua-5.4.7/lvm.h../3rdparty/lua-5.4.7/lzio.c../3rdparty/lua-5.4.7/lzio.h
)add_library(${PROJECT_NAME} SHAREDkernel.cpp${LUA_LIST}
)

核心代码

内核代码

  • kernel.cpp
/****************************************           内核层入口**************************************/#include "Base/SharedData.h"
#include "Business/TaskHandle.h"SharedData *kernel_data_ptr_ {nullptr};         // 全局数据指针
KSHandle kernel_shared_data_handle_ {NULL};     // 共享数据句柄// Task处理回调
KSError __stdcall TaskCallback(void * /*pArgs*/, void * /*pContext*/);// KRTS资源初始化
extern "C" KSError __declspec(dllexport) __stdcall InitFunction(void *pArgs, void * /*pContext*/)
{KS_printK("InitFunction called!\n");// 获取全局数据指针kernel_data_ptr_ = static_cast<SharedData *>(pArgs);// 设置任务专用的CPUerror = KS_setTargetProcessor(kernel_data_ptr_->task_cpu,KSF_NO_FLAGS);if (error != KS_OK) { KS_printK("KS_setTargetProcessor failed!\n"); }error = KS_createCallBack(&kernel_data_ptr_->task_callback_handle, TaskCallback, nullptr, KSF_DIRECT_EXEC | KSF_SAVE_FPU, 0);if (error != KS_OK) { return error; }error = KS_setTaskStackSize(0x100000, KSF_NO_FLAGS);if (error != KS_OK) { return error; }error = KS_createTask(&kernel_data_ptr_->task_handle, kernel_data_ptr_->task_callback_handle, 172, KSF_CUSTOM_STACK_SIZE);if (error != KS_OK) { return error; }return KS_OK;
}// KRTS资源析构
extern "C" KSError __declspec(dllexport) __stdcall ExitFunction(void * /*pArgs*/, void * /*pContext*/)
{KS_printK("ExitFunction called!\n");if (kernel_data_ptr_ == nullptr){return KSERROR_FUNCTION_NOT_AVAILABLE;}// 向任务发出终止信号。kernel_data_ptr_->abort = 1;if (kernel_data_ptr_->task_handle != NULL){KS_removeTask(kernel_data_ptr_->task_handle);}if (kernel_data_ptr_->task_callback_handle != NULL){KS_removeCallBack(kernel_data_ptr_->task_callback_handle);}return KS_OK;
}// 这是实时任务将运行的函数,并对执行 Task 操作。只有实时任务才应调用 Task 函数。
KSError __stdcall TaskCallback(void * /*pArgs*/, void * /*pContext*/)
{// 处理循环,此循环仅在发出中止信号时停止。while (true){// 等待停止的通知。if (kernel_data_ptr_->abort != 0) { break; }// Todo 处理 luaif (kernel_data_ptr_->script_run_status){TaskHandle::OnLuaScript();kernel_data_ptr_->script_run_status = false;}KS_sleepTask(REFRESH_TIME*10*1000);}return KS_OK;
}#pragma pack(push, 8)
#include <windows.h>
#pragma pack(pop)BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD reason, LPVOID pReserved)
{return TRUE;
}

Lua 交互

  • TaskHandle.h
/*****************************************
*
*    lua内核处理
*
*****************************************/#ifndef TASKHANDLE_H
#define TASKHANDLE_Hclass TaskHandle
{
public:TaskHandle();~TaskHandle();//lua 脚本执行static void OnLuaScript();};#endif //TASKHANDLE_H
  • TaskHandle.cpp
#include "TaskHandle.h"
#include "Base/SharedData.h"#pragma pack(push, 8)
extern  "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}
#include <iostream>
#pragma pack(pop)// 方法一 :函数注册
static int FunctionTest(lua_State *lua_state)
{// 获取参数个数const int count = lua_gettop(lua_state);int value {};for (int i = 0; i <= count; i++){// 获取参数类型const int type = lua_type(lua_state, i);// 获取参数值value = lua_tonumber(lua_state, i);// 输出printf("index:%d, type:%d, value:%d\n", i, type, value);}lua_pushnumber(lua_state, value);return 1;
}// 方法二:模块注册
static int FunctionModule(lua_State *lua_state)
{// 获取参数个数const int count = lua_gettop(lua_state);double avg {},sum{};for (int i = 0; i <= count; i++){// 获取参数类型const int type = lua_type(lua_state, i);// 获取参数值const double value = lua_tonumber(lua_state, i);printf("index:%d, type:%d, value:%f\n", i, type, value);sum += value;}avg = sum / count;// 返回参数压入栈中lua_pushnumber(lua_state, avg);lua_pushnumber(lua_state, sum);// 返回的参数个数return 2;
}// 列出需要注册的函数数组
static const luaL_Reg KRTS_FunctionModule[] =
{{"FunctionModule", FunctionModule},{nullptr, nullptr}
};// 将所有函数放到表并压入栈中
int CreateLibs(lua_State *lua_state)
{// 创建一个表luaL_newlib(lua_state, KRTS_FunctionModule);return 1;
}// 注册模块
static const luaL_Reg RegisterModule[] = {{ "base", luaopen_base },   // 基础库{ "KRTS", CreateLibs },     //自定义的模块名字:KRTS{ nullptr, nullptr}
};TaskHandle::TaskHandle()
{}TaskHandle::~TaskHandle() = default;void TaskHandle::OnLuaScript()
{try{// 初始化lua_State *lua_state = luaL_newstate();// 加载lualuaL_openlibs(lua_state);/*****************************************************    方法一: 以函数的形式注册C++普通函数提供给Lua使用*    C++方法: FunctionTest*    lua脚本:*             val = FunctionTest(10)*             print("The value is ", val)****************************************************//* 注册C++函数 */lua_register(lua_state, "FunctionTest", FunctionTest);/******************************************************    方法二: 以模块的方式注册C++普通函数提供给Lua使用*    C++模块: KRTS*       函数: FunctionModule*    lua脚本:*             avg,sum = KRTS.FunctionModule(1,2)*             print("The sum is ", sum)*             print("The avg is ", avg)*****************************************************/for (const luaL_Reg* lua_reg = RegisterModule; lua_reg->func; ++lua_reg){luaL_requiref(lua_state, lua_reg->name, lua_reg->func, 1);lua_pop(lua_state, 1);}//luaL_dostring(lua_state, "print('hello lua')");// 执行lua文件luaL_dofile(lua_state, LUA_FILE_NAME);lua_close(lua_state);}catch (...){printf("lua error\n");}
}

运行结果

index:0, type:4, value:0.000000
index:1, type:3, value:1.000000
index:2, type:3, value:2.000000
The sum is      3.0
The avg is      1.5
--------------------------------
index:0, type:4, value:0
index:1, type:3, value:10
The value is    10.0
--------------------------------

http://www.ppmy.cn/embedded/110039.html

相关文章

RocketMQ异步报错:No route info of this topic

在SpringBoot中发送RocketMQ异步消息的时候报错了&#xff0c;提示org.apache.rocketmq.client.exception.MQClientException: No route info of this topic, testTopic1 这里给出具体的解决方案 一、Broker模块不支持自动创建topic&#xff0c;并且topic没有被手动创建过 R…

【Android】GreenDao数据库的使用方式

需求 使用GreenDao数据库进行数据的存储。 介绍 GreenDao 是一个轻量级的对象关系映射&#xff08;ORM&#xff09;库&#xff0c;用于简化 Android 应用中的数据库操作。它提供了以下主要功能&#xff1a; 简化数据库操作&#xff1a;通过注解定义实体类&#xff0c;Green…

《论层次架构及其在软件系统中的应用》写作框架,软考高级系统架构设计师

论文真题 层次架构作为软件系统设计的一种基本模式,对于实现系统的模块化、可维护性和可扩展性具有至关重要的作用。在软件系统的构建过程中,采用层次架构不仅可以使系统结构更加清晰,还有助于提高开发效率和质量。因此,对层次架构的理解和应用是软件工程师必备的技能之一…

特权指令介绍

特权指令是指具有特殊权限的指令&#xff0c;这类指令通常只用于操作系统或其他系统软件&#xff0c;不直接提供给用户使用。特权指令的权限较高&#xff0c;如果使用不当&#xff0c;可能会导致整个系统崩溃。以下是常见的特权指令及其功能&#xff1a; 有关I/O设备使用的指令…

索尼的Web3蓝图:从技术创新到现实应用的全方位布局

近年来&#xff0c;随着区块链技术和加密资产的迅猛发展&#xff0c;全球科技巨头纷纷投入其中&#xff0c;力图在Web3浪潮中占据一席之地。作为传统科技行业的巨头&#xff0c;索尼(Sony)也不甘落后&#xff0c;积极推动其Web3战略布局&#xff0c;展现出其在新兴领域的强烈野…

2024年录屏神器大盘点,轻松捕捉屏幕精彩

现在讲解一些操作越来越便捷了&#xff0c;我 一般都是用录屏工具来边录制操作边讲解&#xff0c;这样可以更方便对方了解操作步骤。这次我就分享几款免费录屏工具一起来试试吧。 1.福晰录屏软件 链接&#xff1a;www.foxitsoftware.cn/REC/ 对于初次尝试录屏的新手来说&…

FxFactory 8 for Mac 视觉特效插件包安装

Mac分享吧 文章目录 介绍页面效果一、下载软件二、开始安装1、Install安装2、显示软件页面&#xff0c;表示安装成功3、补丁安装 三、注意事项1、若已安装过其他版本&#xff0c;需要使用软件自带的卸载功能进行软件卸载&#xff0c;再安装此版本 安装完成&#xff01;&#x…

被低估的SQL

SQL是现代数据库管理系统中不可或缺的一部分。尽管它的使用已十分普遍&#xff0c;但在数据处理领域&#xff0c;SQL的某些功能和潜力仍然被许多人低估。接下来&#xff0c;小编将与您一起&#xff0c;探讨SQL的一些被忽视的特性&#xff0c;揭示它在数据管理中的真正实力。 1.…