Lua: Вызов функции Lua, которая возвращает строку много раз.Как сделать так, чтобы были поля, которые переходят к следующему экземпляру - PullRequest
1 голос
/ 16 июля 2011

Итак, у меня есть программа на C ++, которая рекурсивно проходит по дереву каталогов и вызывает определенную функцию lua для всех файлов в этом каталоге.

Управление стеком с помощью Lua и C ++

Вы можете прочитать мой предыдущий вопрос, чтобы узнать, как именно это работает, но по сути это довольно просто. Функция lua возвращает 0 для многих строк. Тем не менее, результаты одного возврата Lua могут повлиять на результаты более позднего возврата Lua. (в частности, я пытаюсь удалить дублирующиеся строки и некоторые другие вещи)

Мне интересно, есть ли способ настроить так, чтобы я все еще мог делать эти вызовы lua, но при этом состояние lua оставалось открытым на время рекурсивных операций. Таким образом, я должен сохранять переменные и другую важную информацию во время этого рекурсивного процесса, что позволило бы мне легко расширить функциональность моей программы.

Мое приложение C ++ использует мой интерфейс с открытым исходным кодом, называемый FileDigger, который позволяет мне заполнить логику для выполнения beforeDig () и afterDig () и fileFound ()

на данный момент это мой код:

#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:\n\n Ex: a C:\\cpp\\a .cpp .h";

        int any_number;
        std::cout << "\n\n";
        std::cout << "Please enter a number to end the program:";
        std::cout << "\n\n";
        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 << "\n\n";
    std::cout << "Please enter a number to end the program:";
    std::cout << "\n\n";
    //std::cin >> any_number;
    return 0;
}

Итак, как вы можете видеть, он создает класс FileDigger и Shovel. Лопата - это интерфейс, где вы размещаете свою логику. После того, как они созданы, он запускает рекурсивный процесс, вызывая dig ()

Это вызывает beforeDig (), затем запускает рекурсивный процесс. когда файл найден, он вызывает fileFound (), который затем получает строки и помещает их в вектор. После того, как копание закончено, я просто печатаю строки.

Как вы увидите, я создаю и удаляю состояние в функции fileFound. Я думаю, вместо того, чтобы делать это, я должен запустить состояние Lua в beforeDig () и завершить его в afterDig ().

Кроме того, прямо сейчас мой lua-источник вызывается непосредственно в файле .lua вместо вызова конкретной функции, содержащей этот код. Я думаю, что мне, вероятно, придется изменить это ... Итак ... Если у вас есть еще вопросы, я отвечу на них, но давайте начнем обсуждение! : D

1 Ответ

1 голос
/ 16 июля 2011

Вам понадобится изменить дизайн, как вы используете 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 */

Примечание, обработка ошибок и использование модуля вместо глобального, оставлены как упражнения для читателя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...