KRTSt内嵌Lua脚本

news2024/12/23 6:49:21

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} SHARED
        kernel.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);

    // 设置任务专用的CPU
    error = 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 处理 lua
        if (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_H

class 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();
        // 加载lua库
        luaL_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.coloradmin.cn/o/2112435.html

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

相关文章

什么是网络准入控制系统?网络准入控制系统七大品牌介绍!

在当今信息化时代&#xff0c;企业网络安全面临着前所未有的挑战。网络准入控制系统&#xff08;NAC, Network Access Control&#xff09;作为一种重要的网络安全技术&#xff0c;扮演着守护企业网络安全大门的关键角色。网络准入控制系统通过对接入网络的设备进行身份验证、安…

为什么现在不建议去电力设计院?终于有人把电力设计院说清楚了!

作者&#xff1a;电气哥 最近电气哥收到了许多面临就业的同学特别是硕士同学有关于电力设计院的咨询&#xff0c;那么现在电力设计院到底还值不值得去&#xff1f;电气哥带你来分析一下电力设计院的前世今生。 01 电力设计院的前世今生 曾经&#xff0c;在我国的大基建时代&…

java设计模式--(行为型模式:策略模式、命令模式、责任链模式)

6&#xff0c;行为型模式 行为型模式用于描述程序在运行时复杂的流程控制&#xff0c;即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务&#xff0c;它涉及算法与对象间职责的分配。 行为型模式分为类行为模式和对象行为模式&#xff0c;前者采用继承…

keepalived和lvs高可用集群

keepavlied和lvs高可用集群搭建 主备模式&#xff1a; 关闭防火墙和selinux systemctl stop firewalld setenforce 0部署master负载调度服务器 zyj86 安装ipvsadm keepalived yum install -y keepalived ipvsadm修改主节点配置 vim /etc/keepalived/keepalived.conf! Conf…

鹰眼雾炮适合在哪些场合使用

朗观视觉鹰眼雾炮由于其独特的功能和优势&#xff0c;适合在多种场合使用&#xff0c;主要包括但不限于以下几个方面&#xff1a; 建筑工地&#xff1a;建筑工地是粉尘污染的主要来源之一。鹰眼雾炮可以有效降低施工过程中的扬尘&#xff0c;改善工地及周边空气质量&#xff0c…

南卡科技“满分之选”全新开放式耳机发布,打造超越Pro的极致体验!

在音频技术的不断革新中&#xff0c;南卡品牌以其深厚的声学底蕴和对创新的不懈追求&#xff0c;再次为市场带来惊喜。今天&#xff0c;我们自豪地宣布&#xff0c;南卡OE Pro2开放式蓝牙耳机正式亮相&#xff0c;它不仅代表了南卡在开放式耳机领域的技术巅峰&#xff0c;更是对…

基本和复合逻辑运算

目录 基本逻辑运算 与运算 或运算 非运算 复合逻辑运算 与非运算 或非运算 异或运算 同或运算 基本逻辑运算 与运算 两个都为1才为1&#xff0c;否则为0&#xff0c;类似于编程语言里的&。 有0出0&#xff0c;全1出1。 逻辑表达式就是AB,可以省略中间的点。 逻辑符…

TimescaleDB-3 超表的维护

数采系统上线半年多了&#xff0c;产生了大概2亿条记录&#xff0c;这些数据其实是有时效性的&#xff0c;用来生成的二次数据可以永久保存&#xff0c;这种时序数据没有多大价值&#xff0c;又非常占用空间&#xff0c;所以定期清理超表的trunk是必要的 --1、查看分区表以及…

好用的AI编程助手[豆包]

欢迎来到 Marscode 的世界&#xff01;这里将为你揭秘 Marscode&#xff0c;它的独特之处、应用领域等相关精彩内容等你来探索。 一、打开VS Code 二、选择 Extensions,搜索marscode 三、点击安装 四、点击使用 五、输入需要编写的代码 六、根据自己的需求修改代码 MarsCode 注…

Pytorch多GPU分布式训练代码编写

Pytorch多GPU分布式训练代码编写 一、数据并行 1.单机单卡 模型拷贝 model.cuda() 原地操作 数据拷贝&#xff08;每步&#xff09; datadata.cuda() 非原地操作 基于torch.cuda.is_available()来判断是否可用 模型保存与加载 torch.save 来保存模型、优化器、其他变量tor…

spring security 中的授权使用

一、认证 身份认证&#xff0c;就是判断一个用户是否为合法用户的处理过程。Spring Security 中支持多种不同方式的认证&#xff0c;但是无论开发者使用那种方式认证&#xff0c;都不会影响授权功能使用。因为 SpringSecurity 很好做到了认证和授权解耦。 二、授权 授权&#x…

红黑树的旋转

红黑树的基本性质 红黑树与普通的二叉搜索树不同&#xff0c;它在每个节点上附加了一个额外的属性——颜色&#xff0c;该颜色可以是红色或黑色。通过引入这些颜色&#xff0c;红黑树能够维持以下 5 个基本性质&#xff0c;以确保树的平衡性&#xff1a; 每个节点是红色或黑色…

C++入门10——stack与queue的使用

目录 1.什么是stack&#xff1f; stack的使用 2.什么是queue&#xff1f; queue的使用 3.priority_queue 3.1 什么是priority_queue? 3.2 priority_queue的使用 1.什么是stack&#xff1f; 在官网中&#xff0c;对stack有这样的介绍&#xff1a; Stacks are a type o…

一台电脑对应一个IP地址吗?‌探讨两台电脑共用IP的可能性

在当今数字化时代&#xff0c;‌IP地址作为网络世界中的“门牌号”&#xff0c;‌扮演着至关重要的角色。‌它负责在网络上唯一标识每一台设备&#xff0c;‌使得数据能够在庞大的互联网中准确无误地传输。‌然而&#xff0c;‌对于IP地址与电脑之间的对应关系&#xff0c;‌许…

uni-appH5项目实现导航区域与内容区域联动效果

一、需求描述 将导航区域与内容区域实现联动&#xff0c;即点击导航区域&#xff0c;内容区滚动到对应位置&#xff0c;内容区滚动过程中根据内容定位到相对应的导航栏。 效果如下&#xff1a; 侧边导航与内容联动效果 二、功能实现思路分析汇总&#xff1a; 三、具体代码 1…

Matplotlib通过axis()配置坐标轴数据详解

坐标轴范围设置 axis()可以直接传入列表[xmin,xmax,ymin,ymax]进行范围设置, 分别可以使用plt.axis()或者画布对象.axis()进行配置 import numpy as np import matplotlib.pyplot as pltx np.linspace(0, 20, 100) y x*2 plt.plot(x, y, r) plt.axis([0,30,0,100]) plt.sa…

【精选】文件摆渡系统:跨网文件传输的安全与效率之选

文件摆渡系统可以解决哪些问题&#xff1f; 文件摆渡系统&#xff08;File Shuttle System&#xff09;主要是应用于不同网络、网段、区域之间的文件数据传输流转场景&#xff0c; 用于解决以下几类问题&#xff1a; 文件传输问题&#xff1a; 大文件传输&#xff1a;系统可…

云服务器内网穿透连接云手机配置ALAS

文章目录 服务器安装TailscaleNAT网络&#xff08;无独立IP&#xff09;云服务器安装Tailscale有固定IP的云服务器安装Tailscale 云手机安装Tailscale开启无线网络调试安装Tailscale ALAS连接云手机 上次写到服务器连接云手机时只说了有独立IP的&#xff0c;但有独立IP的云手机…

IDM 工具下载 地图高程数据

巧用IDM工具 快捷下载ASTER GDEM v3高程数据 ASTER GDEM v3是NASA推出的30米高清DEM,覆盖了几乎全部的地球陆地。那么,在NASA官网怎么下载ASTER GDEM v3的地形高程数据呢? 首先,你需要注册一个nasa的账号 注册网址: https://urs.earthdata.nasa.gov/users/new 注册方式和国…

彩虹数字屏保时钟 芝麻时钟开启个性化的时代 屏保怎么能少它

彩虹数字屏保时钟 芝麻时钟开启个性化的时代 屏保怎么能少它&#xff1f;电脑屏保多样化&#xff0c;让大家有了更多的选择&#xff0c;让更多人有机会把自己的电脑打扮得漂漂亮亮&#xff0c;今天小编给大家推荐&#xff1a;芝麻时钟&#xff08;官网下载地址&#xff1a;http…