1 (2022-10-03 00:50:32 отредактировано Serg_)

Тема: Передать таблицу из Lua в С++

Подскажите, как передать таблицу из Lua в C++ и достать оттуда данные ?

В С++ Получить доступ или достать из стека строковую переменную можно просто - с помощью функции:

lua_tostring(L, index) // где index - это номер элемента в стеке.

А вот как получить доступ к таблице и к ее значениям ?

Я нашел такой пример:

static int forLua_get_historical_candles(lua_State* L)
{

lua_pushstring(L, "Size");                              // я помещаю ключ таблицы на вершину стека

lua_gettable(L, -2);                                        // Я помещаю значение из таблицы для этого ключа на вершину стека

lua_getfield(L, -1, "Size");                                // помещаем значение table.Size на вершину стека

std::cout << lua_tonumbe(L, -1) << std::endl;   //теперь я хочу отобразить значение

}

Но он не работает и все sad((

2 (2022-10-03 10:59:16 отредактировано swerg)

Re: Передать таблицу из Lua в С++

Не проверял, но думаю должно быть так:

static int forLua_get_historical_candles(lua_State* L)
{
   lua_pushstring(L, "Size");
   lua_gettable(L, -2);
   std::cout << lua_tonumber(L, -1) << std::endl;
   lua_pop(L, 1);   // <-- вот за это я не особо уверен -- НЕ НАДО эТОГО! см. сообщения ниже
}

3 (2022-10-03 10:50:31 отредактировано Serg_)

Re: Передать таблицу из Lua в С++

swerg пишет:

Не проверял, но думаю должно быть так:

static int forLua_get_historical_candles(lua_State* L)
{
   lua_pushstring(L, "Size");
   lua_gettable(L, -2);
   std::cout << lua_tonumber(L, -1) << std::endl;
   lua_pop(L, 1);   // <-- вот за это я не особо уверен
}

Спасибо, но выводит просто ноль, хотя размер точно отличается от нуля.

4

Re: Передать таблицу из Lua в С++

Давайте начнём с другого
Какой будет эквивалентный код на Lua для требуемой вам функции?

5

Re: Передать таблицу из Lua в С++

И вот еще
Про    lua_pop(L, 1); я зря написал выше, не надо этого. Т.к.:

lua_gettable

int lua_gettable (lua_State *L, int index);

Pushes onto the stack the value t[k], where t is the value at the given index and k is the value at the top of the stack.

This function pops the key from the stack, pushing the resulting value in its place.

6

Re: Передать таблицу из Lua в С++

swerg пишет:

Давайте начнём с другого
Какой будет эквивалентный код на Lua для требуемой вам функции?

local my_table_ = CreateDataSource(code_class_, code_paper_, interval)

size_table = my_table_:Size()

7 (2022-10-03 11:28:01 отредактировано swerg)

Re: Передать таблицу из Lua в С++

Так Size() - это ж не поле в таблице!

В гугле: lua "c++" get table size
Например здесь
[url]https://stackoverflow.com/questions/26643285/get-lua-table-size-in-c[/url]

8

Re: Передать таблицу из Lua в С++

swerg пишет:

Так Size() - это ж не поле в таблице!

В гугле: lua "c++" get table size
Например здесь
[url]https://stackoverflow.com/questions/26643285/get-lua-table-size-in-c[/url]

Это именно поле в таблице, возвращаемой из CreateDataSource:

[url]https://luaq.ru/CreateDataSource.html#param_table_37[/url]

Параметры возвращаемой таблицы
Параметр    Тип    Описание
SetUpdateCallback    function    Позволяет задать пользователю функцию обратного вызова для обработки изменившихся свечек
O    function    Получить значение Open для указанной свечи
H    function    Получить значение High для указанной свечи
L    function    Получить значение Low для указанной свечи
C    function    Получить значение Close для указанной свечи
V    function    Получить значение Volume для указанной свечи
T    function    Получить значение Time для указанной свечи
Size    function    Возвращает текущий размер (количество свечек в источнике данных)

9

Re: Передать таблицу из Lua в С++

А, поле с типом функция
Тогда все выше верно, только не lua_tonumber(L, -1), а вызвать функцию на вершине стека, а уж потом прочитать возвращенное из нее значение.

if (lua_pcall(L, 0, 1, 0) == 0)
     std::cout << lua_tonumber(L, -1) << std::endl;

10 (2022-10-03 19:07:05 отредактировано Serg_)

Re: Передать таблицу из Lua в С++

swerg пишет:

А, поле с типом функция
Тогда все выше верно, только не lua_tonumber(L, -1), а вызвать функцию на вершине стека, а уж потом прочитать возвращенное из нее значение.

if (lua_pcall(L, 0, 1, 0) == 0)
     std::cout << lua_tonumber(L, -1) << std::endl;

    lua_pushstring(L, "Size");
        lua_gettable(L, -1);
        if (lua_pcall(L, 0, 1, 0) == 0)
        std::cout << lua_tonumber(L, -1) << std::endl;

Неа, все равно, теперь даже 0 - не выводится.

lua_pcall(L, 0, 1, 0) - возвращается с ошибкой:

error in error handling

11

Re: Передать таблицу из Lua в С++

Нихрена короче не работает.

12

Re: Передать таблицу из Lua в С++

lua_pushnumber(L, 1);                      //Добавляю в стек номер индекса переданной таблицы к элементу которой я хочу получить доступ.
lua_gettable(L, 1);                        //Помещает на вершину стека переданной таблицы - расположенная по 1 элементу в стеке, и индексу в самой таблице - по номеру элемента с вершины стека, то есть с номера "1", которая я добавил строчкой выше.

lua_getfield(L, -1, "Size");               //Теперь беру значение из стека с вершины стека, то есть то значние, которое я извлек из таблицы по индексу "1" (грубо говоря первая свеча) и извлекаю из него поле с заданным именем "Size" и значение этого поля помещается на вершину стека.

std::cout << "Size:" << lua_tonumber(L, -1) << std::endl;      //Беру значение с вершины стека и получаю дулю с маслом или ошибку "unrecognized exception" в самом квике.

Так тоже нифига не рабоатет.

13

Re: Передать таблицу из Lua в С++

Хотя да. У нас же вот такой вызов

my_table_:Size()

а не вот такой

my_table_.Size()

Попробуйте тогда еще вот такой вариант:

static int forLua_get_historical_candles(lua_State* L)
{
   lua_pushstring(L, "Size");
   lua_gettable(L, -2);
   lua_pushvalue(L, -2); 
   if (lua_pcall(L, 1, 1, 0) == 0)
        std::cout << lua_tonumber(L, -1) << std::endl;}

PS
Вот очень наглядно показаны функции управления стеком Lua
[url]https://www.lua.org/pil/24.2.3.html[/url]

14

Re: Передать таблицу из Lua в С++

А зачем вы все это мучаетесь делаете на Си ?
Сделайте пока код на Lua. Как минимум  для отработки стратегии. Это ж много проще.
А уж если увидите узкие места в производительности - их можно будет на Си переписать.

15

Re: Передать таблицу из Lua в С++

swerg пишет:

А зачем вы все это мучаетесь делаете на Си ?
Сделайте пока код на Lua. Как минимум  для отработки стратегии. Это ж много проще.
А уж если увидите узкие места в производительности - их можно будет на Си переписать.

Код на Lua я уже сделал, но мне нужно в Си в своем приложении.

16

Re: Передать таблицу из Lua в С++

swerg пишет:

Хотя да. У нас же вот такой вызов

my_table_:Size()

а не вот такой

my_table_.Size()

Попробуйте тогда еще вот такой вариант:

static int forLua_get_historical_candles(lua_State* L)
{
   lua_pushstring(L, "Size");
   lua_gettable(L, -2);
   lua_pushvalue(L, -2); 
   if (lua_pcall(L, 1, 1, 0) == 0)
        std::cout << lua_tonumber(L, -1) << std::endl;}

PS
Вот очень наглядно показаны функции управления стеком Lua
[url]https://www.lua.org/pil/24.2.3.html[/url]

Если я правильно понимаю, в данном случае функция lua_pcall - не уместна. В этом случае же не нужно вызывать никаких функций.

17

Re: Передать таблицу из Lua в С++

Делаю так:

    int size_stack = lua_gettop(L);
    std::cout << size_stack << std::endl;         //Размер стека 1

    lua_pushstring(L, "Size");

    size_stack = lua_gettop(L);
    std::cout << size_stack << std::endl;         //Размер стека 2

    lua_gettable(L, -2);                          //lua_gettable - помешает на вершину стека значение Таблицы, которая расположена первый элементом в стеке по ключу расположенному на вершине стека, то есть по ключу "Size"

    size_stack = lua_gettop(L);
    std::cout << size_stack << std::endl;        //Размер стека 2, то есть  lua_gettable - доабвила значение по ключу Size за место доавленной выше строки "Size"

    std::cout << "Size_number:" << lua_tonumber(L, -1) << std::endl;      //Извлекаю значение с вершин стека, НО оно равно НУЛЮ!!! ХОТЯ таблица переданная из Lua в Си - гарантировано имеет размер

Есть у меня подозрение, что в Квике, как всегда какой то косяк и просто тупо что то не работает.

18 (2022-10-04 11:22:55 отредактировано swerg)

Re: Передать таблицу из Lua в С++

Раз Lua-код работает - значит все в QUIK правильно.
Надо просто разобраться с Lua-API

Size - это не просто поле таблицы, это (функция) (возможно, метод метатаблицы).
У меня сейчас нет времени подробно у себя все это воспроизводить и готового кода про это нет, поэтому точно подсказать не могу.

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

19 (2022-10-04 11:37:53 отредактировано swerg)

Re: Передать таблицу из Lua в С++

Serg_ пишет:

Если я правильно понимаю, в данном случае функция lua_pcall - не уместна. В этом случае же не нужно вызывать никаких функций.

Но ведь в Lua вы не просто читаете поле

my_table_.Size

вы же вызываете "метод", причем через двоеточие

my_table_:Size()

Вот примерно похожий вопрос:
[url]https://stackoverflow.com/questions/40551641/call-lua-table-function-from-c-w-self-in-function[/url]

20

Re: Передать таблицу из Lua в С++

Кромешный ад:

lua_pushstring(L, "Size");       //Помещаю на вершину стека название функции "Size"

int status_lua_pcall = lua_pcall(L, 1, 1, 0);    //Вызываю lua_pcall, которая принимает кол-во переданных аргументов - в моем случае это аргумент Size()  - то есть 1, и кол-во результата, которая должна возвратить функция - то есть размер таблицы - то же 1.

    if (status_lua_pcall != 0)
    {
        std::cout << "Error_lua_pcall:" << lua_tostring(L, -1) << std::endl;
    }
    else
    {
        std::cout << "lua_pcall_result:" << lua_tonumber(L, -1) << std::endl;
    }

lua_pcal завершается ошибкой - "error in error handling".

21

Re: Передать таблицу из Lua в С++

Делаю так:

lua_getfield(L, -1, "Size");  //Извлекаю ключ Size из таблицы и помещаю на вершину стека

//Проверяю, что на вершине стека:

    int status_lua_isC_function = lua_iscfunction(L, -1);
    std::cout << "status_lua_isC_function:" << status_lua_isC_function << std::endl;  //return 1


    int status_lua_is_function = lua_isfunction(L, -1);
    std::cout << "status_lua_is_function:" << status_lua_is_function << std::endl;     //return 1

//return 1 - означает на вершине стека - функция - видимо извлеченная функция Size.

    lua_pushvalue(L, -2); // Создаю копию таблицы и помещаю ее на вершину стека после функции Size.

    int status_lua_pcall = lua_pcall(L, 1, 1, 0); // Вызываю функцию Size с аргументом в виде таблицы и одним возвращаемым значением

    if (status_lua_pcall == LUA_ERRERR)
    {
        std::cout << "LUA_ERRERR" << std::endl;
    }

И нифига это не работает, так как lua_pcall - всегда завершается ошибкой LUA_ERRERR - ошибка во время выполнения обработчика ошибок.

Будьте прокляты создатели Lua.

22

Re: Передать таблицу из Lua в С++

Serg_ пишет:

И нифига это не работает,

Отлично работает.
Удивился что никак не получается, потратил время, собрал все это у себя.

С++ код в dll у меня такой:

static int forLua_TestDataSource(lua_State *L) {
    lua_getfield(L, -1, "Size");
    lua_pushvalue(L, -2); 
    if (lua_pcall(L, 1, 1, 0) == 0)
        lua_pushinteger(L, lua_tointeger(L, -1));
    else
        lua_pushstring(L, "ERROR pcall");

    return 1;
}

Вызывающий Lua-код:

dll = require("luacdll")

function main()
    local my_table_, err = CreateDataSource("TQBR", "MSNG", INTERVAL_M1)
    message("Res=" .. tostring(dll.TestDataSource(my_table_)))
end

Выводит:

Res=1

Да, у меня как раз одна свеча по указанному инструменту.
Если указать несуществующий инструмент - выводит Res=0

Так что всё работает. И вроде от приведенного вами кода в сообщении #21 не отличается. Ищите ошибку в сборке.

Как вариант - вы запускаете Lua-скрипт в квике не на той версии Lua, с какой собираете свою библиотеку. Или еще что-то не так, не знаю.

23

Re: Передать таблицу из Lua в С++

swerg пишет:

Так что всё работает. И вроде от приведенного вами кода в сообщении #21 не отличается. Ищите ошибку в сборке.

Как вариант - вы запускаете Lua-скрипт в квике не на той версии Lua, с какой собираете свою библиотеку. Или еще что-то не так, не знаю.

Если бы была проблема в либах Lua - то тогда бы вообще ничего не работало. Но я без проблем предаю оыбчные чилсовые занчения, строки т даже одномерную простуюб таблицу из Lua в С++ - и все прекрасно работает.

А вот с таблицей от CreateDataSource - НЕ РАБОТАЕТ!

24

Re: Передать таблицу из Lua в С++

Подскажите пожалуйста версию quik и версию Lua - на который Вы это запустили ?

25 (2022-10-04 20:58:58 отредактировано Serg_)

Re: Передать таблицу из Lua в С++

static int forLua_TestDataSource(lua_State *L) {
    lua_getfield(L, -1, "Size");
    lua_pushvalue(L, -2); 
    if (lua_pcall(L, 1, 1, 0) == 0)
        lua_pushinteger(L, lua_tointeger(L, -1));
    else
        lua_pushstring(L, "ERROR pcall");

    return 1;
}

Как из этого кода Вы поняли что у Вас работает ??? Я не вижу вывода на консоль размера табилцы.
Выведите именно на консоль, именно в С++ через std::cout.