热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

从.lua的句柄中调用lua函数?-Callingluafunctionsfrom.lua'susinghandles?

Imworkingonasmallprojecttryingtointegrateluawithc++.Myproblemhoweverisasfollows:我

I'm working on a small project trying to integrate lua with c++. My problem however is as follows:

我正在做一个小项目,试图将lua与c++集成在一起。我的问题是:

I have multiple lua scripts, lets call them s1.lua s2.lua and s3.lua. Each of these has the following functions: setVars() and executeResults().

我有多个lua脚本,我们叫它们s1。lua s2。lua和s3.lua。每个函数都具有以下功能:setVars()和executeResults()。

Now I am able to to call a lua file through LuaL_dofile and immediately after use setVars() and/or executeResults(). The problem here however is that after I load s2.lua I can no longer call the functions of s1.lua. This would mean I have to redo the LuaL_dofile on s1.lua to regain access to the function and by doing so I lose access to the functions in s2.lua.

现在,我可以通过LuaL_dofile调用lua文件,并在使用setVars()和/或executeResults()之后立即调用它。但是这里的问题是,当我加载s2之后。lua I不能再调用s1.lua的函数。这意味着我必须重做s1中的LuaL_dofile。为了重新获得对函数的访问权限,我失去了对s2.lua中的函数的访问权限。

Is there a way to simply load all lua files in a row, and afterwards start calling their functions at will? Something like s1->executeResults() s5->executeResults() s3->setVars() etc.

是否有一种方法可以简单地在一行中加载所有lua文件,然后开始随意调用它们的函数?类似s1->遗嘱执行人()s5->遗嘱执行人()s3->setVars()等。

I currently already have a system in place using boost::filesystem to detect all lua files in a folder, I then save these files names in a vector and then simply iterate over the vector to load each lua file in a row.

我目前已经有了一个使用boost::文件系统来检测文件夹中所有lua文件的系统,然后我将这些文件名称保存在向量中,然后在向量上迭代,以在一行中加载每个lua文件。

Foregoing the filling of the vector with lua file names my plugin load function looks like this at the moment:

我的插件加载函数现在看起来是这样的:

void Lua_plugin::load_Plugins(){
 std::vector::const_iterator it;
 for (it=Lua_PluginList.begin(); it!=Lua_PluginList.end(); it++){
  std::cout<<"File loading: " <<*it <

To make it a bit more clear, all I have in the .lua's is something like this:

更清楚一点,我在。lua中的所有东西是这样的

-- s1.lua

setVars()
--do stuff
end

executeResults()
--dostuff
end

etc, but I would like to be able to call s1.lua's setVars() and s2.lua's setVars() after simply having loaded both in a row.

等等,但是我想给s1打电话。lua的setvar()和s2。lua的setVars()在连续加载完这两个文件之后。

3 个解决方案

#1


5  

This is effectively what gwell proposed using the C API:

这就是gwell利用C API提出的有效建议:

#include 

#include "lua.h"

static void
executescript(lua_State *L, const char *filename, const char *function)
{
    /* retrieve the environment from the resgistry */
    lua_getfield(L, LUA_REGISTRYINDEX, filename);

    /* get the desired function from the environment */
    lua_getfield(L, -1, function);

    return lua_call(L, 0, 0);
}

static void
loadscript(lua_State *L, const char *filename)
{
    /* load the lua script into memory */
    luaL_loadfile(L, filename);

    /* create a new function environment and store it in the registry */
    lua_createtable(L, 0, 1);
    lua_getglobal(L, "print");
    lua_setfield(L, -2, "print");
    lua_pushvalue(L, -1);
    lua_setfield(L, LUA_REGISTRYINDEX, filename);

    /* set the environment for the loaded script and execute it */
    lua_setfenv(L, -2);
    lua_call(L, 0, 0);

    /* run the script initialization function */
    executescript(L, filename, "init");
}

int
main(int argc, char *argv[])
{
    lua_State *L;
    int env1, env2;

    L = (lua_State *) luaL_newstate();
    luaL_openlibs(L);

    loadscript(L, "test1.lua");
    loadscript(L, "test2.lua");

    executescript(L, "test1.lua", "run");
    executescript(L, "test2.lua", "run");
    executescript(L, "test2.lua", "run");
    executescript(L, "test1.lua", "run");

    return 0;
}

Test scripts:

测试脚本:

-- test1.lua
function init() output = 'test1' end
function run() print(output) end

-- test2.lua
function init() output = 'test2' end
function run() print(output) end

Output:

输出:

test1
test2
test2
test1

I omitted all error handling for brevity, but you'll want to check the return value of luaL_loadfile and use lua_pcall instead of lua_call.

为了简洁起见,我省略了所有错误处理,但是您需要检查luaL_loadfile的返回值,并使用lua_pcall代替lua_call。

#2


1  

The setfenv() function can be used to create a sandbox or environment for each file loaded.

setfenv()函数可用于为加载的每个文件创建沙箱或环境。

This example shows that all three files could be loaded with conflicting functions and that the functions can be called in any order. Similar code could be written in C++. This example only exports the print function to each environment, more might be needed in your scenario.

这个示例显示了所有三个文件都可以装载相互冲突的函数,并且可以按任何顺序调用这些函数。类似的代码可以用c++编写。这个示例只将打印函数导出到每个环境,在您的场景中可能需要更多。

function newEnv()
  -- creates a simple environment
  return {["print"]=print}
end

local e={} -- environment table
local c    -- chunk variable

-- first instance
c = loadstring([[function f() print("1") end]])
e[#e+1] = newEnv()
setfenv(c, e[#e]) -- set the loaded chunk's environment
pcall(c) -- process the chunk (places the function into the enviroment)

-- second instance
c = loadstring([[function f() print("2") end]])
e[#e+1] = newEnv()
setfenv(c, e[#e])
pcall(c)

-- third instance
c = loadstring([[function f() print("3") end]])
e[#e+1] = newEnv()
setfenv(c, e[#e])
pcall(c)

pcall(e[3].f) --> 3
pcall(e[2].f) --> 2
pcall(e[1].f) --> 1
pcall(e[1].f) --> 1
pcall(e[2].f) --> 2
pcall(e[3].f) --> 3

#3


1  

You could create a new state lua_newstate() for each file. This would be easier than my previous answer. However, it may have a performance penalty.

您可以为每个文件创建一个新的状态lua_newstate()。这比我之前的回答要简单。然而,它可能会有性能损失。


推荐阅读
  • 整整的花了一个下午的时候,才在lua中调用了动态链接库。比起其他脚本语言,lua的调用方式算是比较繁琐的,但是lua的编程思想非常的统一& ... [详细]
  • PHP反射API的功能和用途详解
    本文详细介绍了PHP反射API的功能和用途,包括动态获取信息和调用对象方法的功能,以及自动加载插件、生成文档、扩充PHP语言等用途。通过反射API,可以获取类的元数据,创建类的实例,调用方法,传递参数,动态调用类的静态方法等。PHP反射API是一种内建的OOP技术扩展,通过使用Reflection、ReflectionClass和ReflectionMethod等类,可以帮助我们分析其他类、接口、方法、属性和扩展。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • 本文介绍了GTK+中的GObject对象系统,该系统是基于GLib和C语言完成的面向对象的框架,提供了灵活、可扩展且易于映射到其他语言的特性。其中最重要的是GType,它是GLib运行时类型认证和管理系统的基础,通过注册和管理基本数据类型、用户定义对象和界面类型来实现对象的继承。文章详细解释了GObject系统中对象的三个部分:唯一的ID标识、类结构和实例结构。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • HDFS2.x新特性
    一、集群间数据拷贝scp实现两个远程主机之间的文件复制scp-rhello.txtroothadoop103:useratguiguhello.txt推pushscp-rr ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • Ansibleplaybook roles安装redis实例(学习笔记二十九)
    1、相关redis参数:2、templatesredis.conf配置相关参数:daemonizeyespidfilevarrunredis_{{red ... [详细]
author-avatar
鸳鸯520_205
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有