多次调用返回字符串的Lua函数.如何使它有跨到下一个实例的字段

Lua: Calling Lua function which returns a string, many times. How to make it so there are fields which cross over to the next instance

本文关键字:下一个 字段 实例 何使它 函数 调用 返回 字符串 Lua      更新时间:2023-10-16

那么,我有一个c++程序,它递归地遍历目录树并对该目录中的所有文件调用某个lua函数。

用Lua和c++管理栈

你可以阅读我之前的问题,了解它是如何工作的,但本质上它很简单。lua函数对多个字符串返回0。但是,一次lua返回的结果可能会影响以后一次lua返回的结果。(具体来说,我试图删除重复的字符串和其他一些东西)

我想知道是否有一种方法可以设置,以便我仍然可以进行这些lua调用,但在递归操作期间保持lua状态打开。这样,在这个递归过程中,我应该保留变量和其他重要信息,这将允许我轻松地扩展程序的功能。

我的c++应用程序使用我的开源接口FileDigger,它允许我填写逻辑来执行beforeDig()和afterDig()和fileffound ()

目前这是我的代码:

#include "LanguageShovel.h"
#include <FileDigger/src/FileDigger.h>
#include <fstream>
#include <iostream>
extern "C" {
#include <lua/src/lua.h>
#include <lua/src/lauxlib.h>
#include <lua/src/lualib.h>
}
void LanguageShovel::BeforeDig(string path) {
    cout << "Searching Files..." << endl;
}
void LanguageShovel::AfterDig(string path) {
    for (int i = 0 ; i < list_strings.size(); i++) 
    {
        cout << list_strings[i] << endl;
    }
    cout << list_strings.size() << endl;
    cout << "Finished..." << endl;
}
void LanguageShovel::FileFound(string path) {
    list_strings.push_back(path);
    int error = 0;
    lua_State *L = lua_open();
    luaL_openlibs(L);
    // Push function to stack
    if ((error = luaL_loadfile(L, "src/language.lua")) == 0)
    {
        // Push path to stack
        lua_pushstring(L, path.c_str());
        // Pop stack and call lua script, to return a single table
        if ((error = lua_pcall(L, 1, 1, 0)) == 0)
        {
            // If single value on stack, and is table
            if (lua_gettop(L) == 1 && lua_istable(L,-1))
            {
                int len = lua_objlen(L,-1);
                // list_strings.reserve(len);
                for (int i=0; i < len; i++)
                {
                    // Push index on stack for gettable
                    lua_pushinteger(L,i + 1);
                    lua_gettable(L,-2);
                    size_t strLen = 0;
                    const char *s = lua_tolstring(L,-1, &strLen);
                    if (s)
                    {
                        // Lua strings may not be null terminated
                        // Assign will ensure null terminated end
                        list_strings.push_back(s);
                        list_strings.back().assign(s,strLen);
                    }
                    // Pop the string when finished with it
                    lua_pop(L,1);
                }
            }   
        }
    }
    lua_close(L);
}
void LanguageShovel::DirectoryFound(string path) {
}
int main(int argc, char *argv[]) {
    if( argc < 2 ) {
        cout << "Not enough arguments:nn Ex: a C:\cpp\a .cpp .h";
        int any_number;
        std::cout << "nn";
        std::cout << "Please enter a number to end the program:";
        std::cout << "nn";
        std::cin >> any_number;
        return 1;
    }
    FileDigger f;
    LanguageShovel s;
    string directory = argv[1];
    // Get filters from arguments
    for (int i = 2; i < argc; i++) {
        s.AddFilter(argv[i]);
    }
    f.Dig(directory, s);
    int any_number;
    std::cout << "nn";
    std::cout << "Please enter a number to end the program:";
    std::cout << "nn";
    //std::cin >> any_number;
    return 0;
}
如你所见,它创建了一个FileDigger类和一个Shovel。铲子是你放置逻辑的界面。在创建这些之后,它通过调用dig() 来启动递归过程。

调用beforeDig(),然后开始递归过程。当找到文件时,它调用fileFound(),然后获取字符串并将它们放入向量中。在挖掘完成后,我只是打印字符串。

您将看到,我在fileFound函数中创建并删除了一个状态。我在想,我应该在beforeDig()中开始一个Lua状态,并在afterDig()中结束它,而不是这样做。

而且,现在我的lua源代码是直接在.lua文件中调用的,而不是调用包含该代码的特定函数。我想我可能需要改变一下……所以…如果你还有问题,我会回答的,现在让我们开始讨论吧!: D

您将需要重新设计如何使用Lua。您将在脚本之前调用setup或init函数来设置Lua状态,如下所示:

init_lua() {
  lua_State *L = lua_open();
  luaL_openlibs(L);
  luaL_loadfile(L, "src/language.lua");
  return L;
}

在Lua中,您需要定义在函数调用之间使用的函数和局部变量:

local data_store -- this is where you cache data between function calls
function my_func (path)
  -- do something with path and your data_store
end

回到你的程序,你检索并调用你的函数,而不是重新加载/编译脚本:

lua_getglobal(L, "my_func");
lua_pushstring(L, path.c_str());
lua_pcall(L, 1, 1, 0);
/* etc */

注意,错误处理和使用模块代替全局变量,留给读者作为练习。