Спасибо этому форуму за советы и подсказки. Как принять в dll таблицу с целочисленными ключами, разобрался. Прошу подсказать как внутри dll разобрать по полям более сложную таблицу.
Код
qt=getQuoteLevel2(class, sec)
Согласно документации она возвращает таблицу, в которой два стринга и две вложенных таблицы. Мне нужны для работы все четыре. Как мне, к примеру, получить объём из 3-й котировки на покупку?
Для разбора таблицы с целочисленными индексами мой код внутри dll выглядит так:
Код
static int forLua_SumArray(lua_State* L) {
// Get the length of the table (same as # operator in Lua)
int n = lua_objlen(L, 1);
double sum = 0.0;
// For each index from 1 to n, get the table value as a number and add to sum
for (int i = 1; i <= n; ++i) {
lua_rawgeti(L, 1, i);
sum += lua_tonumber(L, -1);
lua_pop(L, 1);
}
lua_pushnumber(L, sum);
return 1;
}
Пользователь
Сообщений: Регистрация: 20.02.2016
31.08.2018 12:26:16
не проще взять готовый порт ? LuaInterface, luabind и т.п. ? ))
Пользователь
Сообщений: Регистрация: 29.03.2017
31.08.2018 13:28:14
Может быть и проще, но я ничего про это не знаю. Расскажите пожалуйста общий смысл.
Пользователь
Сообщений: Регистрация: 11.11.2015
31.08.2018 15:18:27
Цитата
Let_it_go написал: Может быть и проще, но я ничего про это не знаю. Расскажите пожалуйста общий смысл.
Пишется класс в который оборачивается указатель на стейт. Пишутся сервиные функции по типу чтения/записи с/на стек разного типа переменных. использование регистра. вызова функции. создания таблиц и т.д. вобщем обертка над lua c api. Дальше шаблонные функции исходя из того что им передают вызывают lua c api. для каждого параметра. В итоге код досточно простой получается.
Код
void OnMain(lua::qlua q)
{
lua::table t = q.getQuoteLevel2("SPBFUT", "RIM8");
int bid_count = t["bid_count"];
if (bid_count < 3) return;
lua::table bid = t["bid"];
if (bid == nil) return;
lua::table bid3 = bid[3];
const char* price = bid3["price"];
const char* quantity = bid3["quantity"];
}
extern "C" __declspec(dllexport) int luaopen_testlib(lua_State *L)
{
lua::qlua q(L);
q["main"] = OnMain; //все что нужно для регистрации колбека (шаблон сам раскрывает параметры со стека исходя из сигнатуры функции и передает их в функцию выше.
}
Готовые такие врапперы например 1) 2) Как их подключать и использовать описано в каждом из проектов. В основном это просто заголовочные файлы. все достаточно просто, скачиваете, делаете include и готово)Мне вот например синтаксис использования этих врапперов не зашел. Пришлось изучить их вдоль и поперек и сам апи луа, в итоге свой враппер реализовал) но это долгий путь. лучше готовое взять. selene вполне неплох. ps. еще на форум выкладывали враппер на макросах. где и функции+таблицы из qlua уже описаны были. тоже можно попробывать, как вариант.
Пользователь
Сообщений: Регистрация: 29.03.2017
31.08.2018 15:30:27
Антон, спасибо. 1. Проект создавать как и раньше в виде dll? 2. Код который вы написали, одинаковый для обоих врапперов?
Пользователь
Сообщений: Регистрация: 29.03.2017
31.08.2018 15:44:36
и ещё вопрос. Я понял суть врапперов, естественно с ними проще. но всё же, как решить мою задачу без них? принять таблицу-стакан из OnQuote внутри dll? я сейчас читаю книгу по Луа, написанную её разработчиком. Иду шаг за шагом по главе "C API". В голове каша, но первые проблески уже есть. Строки и числа я уже спокойно обрабатываю в dll.
Пользователь
Сообщений: Регистрация: 20.02.2016
31.08.2018 16:58:06
какой язык предпочтителен ? C / C++ / C#
Пользователь
Сообщений: Регистрация: 11.11.2015
31.08.2018 21:25:15
Цитата
Let_it_go написал: но всё же, как решить мою задачу без них?
например так:
Код
void getQuote3(lua_State* L) {
// t = getQuoteLevel2(c_code, s_code)
lua_getglobal(L, "getQuoteLevel2"); //поместить на стек функцию
lua_pushstring(L, "SPBFUT"); //дальше идут параметры
lua_pushstring(L, "RIM8");
int num_args = 2, num_ret = 1;
lua_pcall(L, num_args, num_ret, 0); //вызываем функцию, на стеке окажется таблица
lua_getfield(L, -1, "bid_count"); //из таблицы по индексу -1 взять значение ключа "bid_count" и поместить на стек
int bid_count = lua_tointeger(L, -1);
if (bid_count < 3) return;
//на стеке -2 = t(table), -1 = bid_count(int)
lua_getfield(L, -2, "bid"); //на стек положит таблицу со значениями стакана(bid)
//на стеке -3 = t(table), -2 = bid_count(int), -1 = bid(table)
lua_rawgeti(L, -1, 3); //из таблицы по индексу -1 взять значение ключа [3] и поместить на стек(еще 1 таблица=bid3)
//на стеке -4 = t(table), -3 = bid_count(int), -2 = bid(table), -1 = bid3(table)
//ну и из последней таблицы получаем необходимы значения
lua_getfield(L, -1, "price");
lua_getfield(L, -2, "quantity");
const char * quantity = lua_tostring(L, -1);
const char * price = lua_tostring(L, -2);
//на стеке -6 = t(table), -5 = bid_count(int), -4 = bid(table), -3 = bid3(table), -2 = price(string), -1 = quantity(string)
lua_pop(6); //чистим стек
}
Пользователь
Сообщений: Регистрация: 29.03.2017
31.08.2018 21:52:49
Антон, спасибо!!! К тому моменту как увидел ваш ответ, уже накорябал свой вариант, но по прежнему не знал как читать вложенные таблицы (стакан и его поля).
Код
static int forLua_OnQuoteC(lua_State* L) {
lua_pushnil(L);
int s = 0;
while (lua_next(L, -2))
{
s = s + 1;
const char* key = lua_tostring(L, -2);
double val = lua_tonumber(L, -1);
lua_pop(L, 1);
}
return 1;
}
Пользователь
Сообщений: Регистрация: 29.03.2017
31.08.2018 23:13:33
Антон, ура, скомпилировалось! Я даже нашёл у вас опечатку
Код
lua_pop(L,6); //чистим стек (забыли букву L)
Но работать пока не работает.
Помогите пожалуйста написать финальные штуки (на них выскакивают ошибки) и.... вы сделали мой день :)
Если вы пытаетесь скомпилировать функцию предложенную Антоном как есть то там ошибка в объявлении функции. Вместо void getQuote3(lua_State* L) { ....
Надо писать
static int getQuote3(lua_State* L) { .... return 0 }
это обязательный формат для всех регестрируемых в луа С функций
Пользователь
Сообщений: Регистрация: 11.11.2015
01.09.2018 01:03:37
Просто думал вызов будет каким-то таким, не ошибка)
Код
static int forLua_SumArray(lua_State* L) {
getQuote3(L);
/* остальное */
}
Но вообще да. я код не компилил и не проверял на 100% правильность так что возможно гдето еще недочеты. Если нужно этот код из lua вызывать то да, все функции которые пробрасываем в луа
Код
lua_CFunction=int(lua_State*)
что компилятор вам и указал во 2й строке скриншота
Пользователь
Сообщений: Регистрация: 29.03.2017
01.09.2018 16:28:16
Код компилируется без ошибок, формируется dll-файл, но в error list остались ошибки.
Последние две указывают на строчку 49:
Полный текст кода сейчас такой:
Код
#include "stdafx.h"
#define LUA_LIB
#define LUA_BUILD_AS_DLL
extern "C" {
#include "lauxlib.h"
#include "lua.h"
#include "lauxlib.h"
}
// стандартная точка входа для DLL
BOOL APIENTRY DllMain(HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
static int getQuote3(lua_State* L) {
// t = getQuoteLevel2(c_code, s_code)
lua_getglobal(L, "getQuoteLevel2"); //поместить на стек функцию
lua_pushstring(L, "SPBFUT"); //дальше идут параметры
lua_pushstring(L, "RIU8");
int num_args = 2, num_ret = 1;
lua_pcall(L, num_args, num_ret, 0); //вызываем функцию, на стеке окажется таблица
lua_getfield(L, -1, "bid_count"); //из таблицы по индексу -1 взять значение ключа "bid_count" и поместить на стек
int bid_count = lua_tointeger(L, -1);
if (bid_count < 3) {
return 0;
}
//на стеке -2 = t(table), -1 = bid_count(int)
lua_getfield(L, -2, "bid"); //на стек положит таблицу со значениями стакана(bid)
//на стеке -3 = t(table), -2 = bid_count(int), -1 = bid(table)
lua_rawgeti(L, -1, 3); //из таблицы по индексу -1 взять значение ключа [3] и поместить на стек(еще 1 таблица=bid3)
//на стеке -4 = t(table), -3 = bid_count(int), -2 = bid(table), -1 = bid3(table)
//ну и из последней таблицы получаем необходимы значения
lua_getfield(L, -1, "price");
lua_getfield(L, -2, "quantity");
const char * quantity = lua_tostring(L, -1);
const char * price = lua_tostring(L, -2);
//на стеке -6 = t(table), -5 = bid_count(int), -4 = bid(table), -3 = bid3(table), -2 = price(string), -1 = quantity(string)
lua_pop(L, 6); //чистим стек
return 0;
}
static const struct luaL_Reg mylib[] = {
{"l_getQuote3", getQuote3},
{NULL, NULL} /* sentinel */
};
extern "C" LUALIB_API int luaopen_Stakan(lua_State *L) {
luaL_openlib(L, "Stakan", mylib, 0);
return 0;
}
Пользователь
Сообщений: Регистрация: 20.02.2016
03.09.2018 14:01:52
всё зависит от проекта. Какая версия компоновщика. версия IDE что у вас в #include "stdafx.h"
Пользователь
Сообщений: Регистрация: 11.11.2015
03.09.2018 16:55:51
Павел Валин, да там все верно. ошибки такие с которыми dll точно бы не сбилдилась. старые мб остались. не видит функции с которыми длл билдится. ерунда вобщем
проверил на vs2017 все ок. ошибок с кодом выше 0.
Пользователь
Сообщений: Регистрация: 20.02.2016
03.09.2018 16:59:42
Антон, угу. я даж с поддеркой CLR это запустить смог. короч странно да. Пару раз мне такую же шляпу написало. но слинковал и всё запустилось. кэш зло )