Обмен данными между Lua и Сpp осуществляется через Lua-стэк, то есть через специальным образом структурированное (по принципу Last In — First Out) пространство.
Иллюстрация процесса добавления переменных в Cтэк (Push) и извлечения переменных из Стэка (Pop).
Иными словами, Lua стэк — это одномерный массив переменных (список, строка) с прямой (от 1 до n) индексацией.
Заполняется стэк командами lua_push (С-side) :
void lua_pushnumber (lua_State *L, lua_Number n);
const char *lua_pushstring (lua_State *L, const char *s);
и другими.
Новой переменной в стэке Луа длинной n автоматически присваивается индекс [n+1] или [-1], где n+1 — абсолютный индекс переменной, а -1 — индекс новой переменной относительно конца (!) стэка.
Доступ, к переменным, соответственно осуществляется функциями lua_to (C-side) :
lua_Number lua_tonumber (lua_State *L, int index);
const char *lua_tostring (lua_State *L, int index);
где L — указатель Lua-стэка, а index — абсолютный или относительный индекс переменной в стэке.
Справочное руководство по Lua API.
Функции С, предназначенные для использования Lua, определяются как :
static int Func(Lua State *L)
{
lua_push...
return(N);
}
где N — число переменных, находящихся в конце (на вершине) стэка Lua и поддерживающие параллельное присвоение в Lua.
Так, например, если стэк содержит 10 переменных, то return(2) вернет 9-ую и 10-ую переменную в Lua.
Lua-side:
CppDLL=require('CppDLL');
Var9,Var10 = CppDLL.Func();
Справка по регистрации функций в языке С++, для вызова их со стороны Lua.
Рассмотрим пример передачи 2D массива типа Double из С++ в Lua :
lua_settop(L,0); // Очищаем Lua стэк
lua_createtable( L, row, 0 ); // создаем луа - таблицу (строки)
for (i=0;i<row;i++)
{
lua_pushinteger(L,i+1);
lua_createtable(L,col,0); // создаем луа-таблицу соответствующую i-ой строке
for(j=0;j<col;j++) // записываем строку в цикле
{
lua_pushinteger(L,j+1); // задаем индекс j-ого элемента i-ой строки
lua_pushnumber( L, arr[i+j*row] ); // задаем значение j-ого элемена i-ой строки
//lua_settable(L, -3); // записываем элемент [i][j] в строку i и очищаем пару [индекс j, значение] из стэка LUA
lua_rawset(L, -3); // записываем элемент [i][j] в строку i и очищаем пару [индекс j, значение] из стэка LUA
}
//lua_settable(L,-3); // добавляем строку i к существующей Lua таблице и отчищаем пару [индеск строки, строка в Lua стэке]
lua_rawset(L,-3); // добавляем строку i к существующей Lua таблице и отчищаем пару [индеск строки, строка в Lua стэке]
}
return(1); // Возвращаем в LUA таблицу, записанную в стэке под индексом 2
Поскольку Lua не поддерживает 2D массивы, то матрицы задаются в качестве массива массивов (строки, элементы которых тоже строки), для чего нам приходится реализовывать связку :
lua_createtable ( указатель стэка, число элементов, 0);
Цикл записи элементов
{
lua_push integer (указатель стэка, индекс нового элемента в строке);
lua_pushnumber ( указатель стэка, значение нового элемента в строке);
lua_rawset( указатель стэка, индекс строки в стэке Lua); *
}
во вложенном цикле.
* Функция rawset добавляет в указанную индексом строку элемент под индексом, определенным предпоследним в стэке и со значением, определенным последним в стэке. После чего удаляет пару [индекс, значение] из стэка, освобождая его.
Аналогичным образом осуществляется чтение матрицы Lua со стороны Cpp :
Узнаем размеры матрицы :
int row=lua_objlen(L,-1); // Узнаем число строк в таблице
lua_pushnumber(L,1); lua_rawget(L,2); // выделяем 1-ую строку из таблицы
int col=lua_objlen(L,3); // Узнаем число столбцов в таблице
В данном примере под индексом [1] в стэке находится имя таблицы, [2] — cама таблица, [3] — индекс строки таблицы до вызова rawget, строка таблицы после вызова rawget.
Считываем матрицу Lua в массив C++ «ptr» :
for (i=0;i<row;i++) // пробегаем по строкам
{
lua_settop(L,2); // очищаем побочный стэк
lua_pushnumber(L,i+1); // номер строки к загрузке
lua_rawget(L,2); // Загрузка строки в переменную 3
for (j=0;j<col;j++) // пробегаем по столбцам
{
lua_pushnumber(L,j+1); // номер столбца к загрузке
lua_rawget(L,3); // Загрузка элемента [i][j] в переменную 4
ptr[i+j*row]=lua_tonumber(L,4); //Записываем значения из Lua в Матлаб
lua_settop(L,3); //Убираем лишние переменные из стэка
}
}
Демонстрация работы программы, считывающей массивы строк и чисел из Cpp в Lua под именами «ACell», «ADouble» и возвращающей в Cpp те же массивы под именами «BCell», «BDouble»:
Предложения и критика приветствуются.
Торгуйте алгоритмами.
С уважением, Кот-Бегемот.
возвращает кол-во элементов, один, таблицу, лежащую на вершине стека
сначала на стеке только таблица(а не ее имя). но можно и по имени ее получить дополнив вызовом lua_getfield, чтобы получить уже таблицу(или что там будет лежать по имени которое передаем.
совет, для новичков нужно бы подправить показывая что происходит со стеком после каждого вызова. так наглядней и проще описать что там происходит.
и еще пример последний стоит заменить на что-нить использующее описанный выше него функционал а не матлабовский скрипт. чтобы могли сразу попробовать то что изучили. мол вот так все легко.
на офф сайте есть шикарная документация по функциям и что они делают со стеком. www.lua.org/manual/5.1/manual.html
проверил кодом:
Вы правы — возвращает вершину стэка.
Текст поправил.
Впрочем, было время (а может и сейчас можно), когда данные можно было напрямую из виртуальной памяти квика высчитывать. На древних версиях без проблем было, сейчас возможно шифруют. Скорость была бешенной.
Скачать ее и мануал можно с сайта ARQA.
Хотя, с заявками сделками можно и непосредственно через Луа работать.