Антон (band) (Все сообщения пользователя)

Выбрать дату в календареВыбрать дату в календаре

Страницы: 1
Отладка QUIK 8.6
 
Anton, и да память она такая. конечно же
luaL_ref(L, LUA_REGISTRYINDEX);
Отладка QUIK 8.6
 
Цитата
Anton написал:
ссылка-то от luaL_ref в какую таблицу попадет, в ту самую, что вам квик передал на стеке. И тот же luaL_ref ее со стека выбросит. И все, стек пустой, что вы из реестра вытащите вообще загадка великая есть.
ссылка попадет в регистровую таблицу а не в ту что лежит на стеке. и да, со стека эта таблица уйдет. но она будет в регистровой таблице по индексу "ref" и поэтому удалять ее lua не должна!
потом lua_rawgeti(L, LUA_REGISTRYINDEX, ref) как раз положит на стек значение из регистровой таблице по индексу ref(наша табличка).
и да код для иллюстрации. используются биндинги. я их лишь перевел в с-апи(по памяти) чтобы уж точно понятно все было. (ошибся вот где lua_tolstring(s, -1, &len); надо lua_tolstring(L, -1, &len);)
но сам принцип рабочий. оно иначе бы не работало сутками напролет.
Отладка QUIK 8.6
 
Цитата
Sergey Gorokhov написал:
Вы же сами пишите "Аналогичная ошибка" к теме про падения.Если у Вас терминал не падает, это уже далеко совсем не "аналогичная" ошибка

Вы так хотите чтобы он упал?) Поверьте из dll его уронить легче некуда.

У (Юрий) он вылетает как и у нас на открытии, но он не может сказать в чем дело.
мы расписали в чем дело было у нас и как мы это поправили.
Но Вы считаете что это не связанно?... Вам же помочь исправить все хотим.

Еще разок распишу конешно, мне не жалко..
=============================
Вылетает при конекте к серверу(до торгов) когда старый данные чистятся терминалом.
Вылетает как раз на тиковом колбеке говоря что таблица которую нам дал терминал == nil.
обработка идет примерно так.

Код
int on_all_trade(lua_State* L) {
  int ref = luaL_ref(L, -1)

  lua_rawgeti(L, LUA_REGISTRYINDEX, ref); //вернет nil на стек вместо table 
  lua_getfield(L, -1, "class_code"); //вернет nil на стек вместо string
  
  size_t len;
  const char* p = lua_tolstring(s, -1, &len); //p==nil (тк на стеке nil)
  std::string val(p, len); //как раз исключение будет и терминал бахнет c дампом.
  return 0;
}

=============================
Дампов не сохранилось. Квик работает после введений проверок стабильно.
Ошибка редкая. Буду ждать фикса по дампам которые вам уже отправил Юрий, тк свою проблему(возникающую в тот же момент что и у Юрия) я и Андей смогли решить проверяя данные которые нам приходят в колбеки.
Отладка QUIK 8.6
 
Цитата
Юрий написал:
У меня сегодня тоже упал опять, архив отправил разработчикам. Уже третье падение квика в момент подключения к серверам брокера еще до открытия торговой сессии.  
Аналогичная ошибка. работает 5-7 дней супер стабильно. при подключении к серверу (перед открытием торгов) вываливается в функции OnAllTrade(t) при попытки получить t["price"].
до взятия цены отрабатывают стабильно :
           t["class_code"]
           t["sec_code"]
           t["datetime"]
           t["price"] -- говорит что такой таблицы нет(t==nil). а предыдущии данные валидные все ок. долго думал мб где напортачил а оказывается не у меня одного...

и терминал не падает. ловится ошибка и скрипт ее отрабатывает. но пришлось поставить на все данные проверки типов. :)
DLL и Lua, Ошибка
 
забыл, lua_newthread на стек добавит поток. запоминаем в регистр чтобы ГЦ не потер его(заодним со стека уберем, ни к чему он там). luaL_ref(L, LUA_REGISTRYINDEX);
DLL и Lua, Ошибка
 
SnamI, в своем потоке лучше не делать lua_newthread
Код
static void test(lua_State *L)
{        
    using namespace std::chrono_literals;
    for (size_t i = 0; i < 5000; i++)
    {
        lua_getglobal(L, "message");
        lua_pushstring(L, "test");
        lua_pcall(L, 1, 0, 0);
        std::this_thread::sleep_for(1ms);
    }
}

static int forLua_StartProgramm(lua_State *L)
{
    lua_State *tL = lua_newthread(L);
    std::thread thr(test, tL);
    thr.detach();
    return 0;
}
есть основной поток квика. есть поток скрипта(функция main). если создать свой поток и начать писать в стек с которым идет паралельная работа (в этих 2х потоках) без синхронизации пойдет одновременная запись. стек будет битый и это приводит к таким ошибкам.
DLL и Lua, Ошибка
 
Цитата
SnamI написал:
std::thread thr(test, L); //Запускает выполнение функции в отдельном потоке
Так делать нельзя. Вы в потоке используете стек, который может использовать квик/ваш скрипт.
создайте новый луа_стейт под этот поток. запомните куданить в регистр например функцию message. ну и работайте с этим стейтом из потока своего. все будет работать.
ошибка в функции TRANS2QUIK_TRADE_DATE
 
Для 1.2 значение верное, спасибо. Если нет возможности перейти на х64, подойдет ли 1.2 или стоит также проверять все данные?
точнее нужно ли планировать переход на х64 тк в 1.2 могут сейчас/позже быть такие же нюансы как в 1.1 с датой сделки?
ошибка в функции TRANS2QUIK_TRADE_DATE
 
QUIK_JUNIOR 7.27.1
TRANS2QUIK v1.1.0.9(1.1)
UID = 138159

совершена такая сделка(в таблице квика именно такие данные и они верны)
TradeId=20393832
TradeDate=18.04.2019
TradeTime=20:58:08
SettleDate=19.04.2019(дата расчетов)
OrderId=219895624

при экспорте через TRANS2QUIK в программу
используя такую декларацию(delphi):
function TradeSettleDate(nTradeDescriptor: integer): integer; stdcall; external DllName name '_TRANS2QUIK_TRADE_SETTLE_DATE@4';
function TradeDate(nTradeDescriptor: integer): integer; stdcall; external DllName name '_TRANS2QUIK_TRADE_DATE@4';
function TradeTime(nTradeDescriptor: integer): integer; stdcall; external DllName name '_TRANS2QUIK_TRADE_TIME@4';

получаю такие данные
TradeDate=20190419
TradeTime=205808
SettleDate=20190419

экспортирую 19.04.2019 в 16-30msk(возможно влияет, я уже не знаю куда копать)
в общем TRANS2QUIK не верно дату сделки возвращает используя '_TRANS2QUIK_TRADE_DATE@4'
19е число вместо 18.
почему?

ps. при экспорте через lua данные datetime
{ ["week_day"] = 4,["hour"] = 20,["ms"] = 160,["mcs"] = 160000,["day"] = 18,["month"] = 4,["sec"] = 8,["year"] = 2019,["min"] = 58,}
тоесть все нормально
DLL для LUA: Ошибка при получении индексированного массива из DLL, В LUA-скрипте при получении индексированного массива из DLL-библиотеки возникает ошибка и QUIK "падает"
 
Алексей, не тот lib файл, либо криво собран.
заменил на тот что идет из поставки Lua_For_Windows, для простоты залил судаhttps://yadi.sk/d/D2kMgI1Cj7FfeQ
больше ничего не трогал. просто заменить 1 файл
ps для своего проекта билд настроен отсуда https://github.com/LuaDist/lua.git . проблема выплыла таже(был очень удивлен, похоже придется менять).

тест уменьшил вплоть до создания пустой таблицы, потом вылетает ошибка VM
Код
#define LUA_LIB
#define LUA_BUILD_AS_DLL

extern "C" {
    #include <lua.h>
    #include <lauxlib.h>
    #include <lualib.h>
    #include <luaconf.h>
}
extern "C" __declspec(dllexport) int luaopen_table_export(lua_State *L)
{
    lua_newtable(L);
    lua_setglobal(L, "asd");
    return 0;
}
ошибку можно убирать разными хаками типа не заполнять 1й элемент начинать со 2го либо заполнить нулевой. не передавать пустые таблицы, но лучше ее на корню исправить используя оригинальные сорцы этой версии(из квика) луа.
динамический заказ тиковых данных
 
Цитата
Imersio Arrigo написал:
Так и есть. Только счётчик уменьшается по ds:Close().
похоже нет, раз
Цитата
Sergey Gorokhov написал:
Соответственно и отказ от подписки в одном скрипте приведет к отказу во всем терминале и во всех скриптах.
значит ds:close может нарушить работу других скриптов. и нет функции чтобы проверять закрыты ли подписки(после того как мы их открыли, другими скриптами)не плохо было бы проверять, а не закрыл ли другой скрипт мою подписку(или я его). но это реально ерунда тк такого в нормальных программах происходить не должно. (1 скрипт нарушает работу другого, закрывая получение данных)
Цитата
Sergey Gorokhov написал:
Не понятно с чем надо согласиться, Вы же сами говорите что проверка не нужна.
в том что я правильно понял как все работает. спасибо, сэкономили кучу времени, вопрос можно считать закрытым.
динамический заказ тиковых данных
 
Т.е. если я хочу проверить открытые подписки я должен пройтись по списку инструментов. создать для каждого
ds = createdatasource(c_code, s_code, interval_tick)
что не приведет к заказу данных(допустим он закрыт для этой бумаги в терминале)
а дальше проверить открыта ли уже подписка в терминале я не могу. но могу закрыть подписку вызвав close, так?
и терминал перестанет данные получать даже если подписка была открыта другими скриптами и они с этими данными работают?

Цитата
Sergey Gorokhov написал:
Нет не логично, от куда терминал знает нужна скрипту эта подписка или нет? может он ее использует через OnAllTrade или вообще скрипту она понадобится как-нибудь потом.Скрипт должен сам сообщить терминалу когда надо закрыть подписку и для этого есть Close.
Как раз таки по наличию ds и может знать. удаляем ds из скрипта. уменьшаем счетчик ссылок. когда он равен 0 то происходит отписка. все для этого имеется. ну ладно об этом уже пару лет назад вам отписывали, не переубедить.

ну хоть на счет проверки подписки тиковых данных согласны? про ТТП и проверку заказа на параметр? или вы считаете раз у вас так контроль подписки работает то и данные функции не нужны. если я хочу удалить подписку то удаляю. если заказать то заказываю. без всяких проверок открыта она уже или нет тк. терминал не ведет контроль того кто эти подписки заказывал и используются ли они до сих пор.
правильно понимаю?
динамический заказ тиковых данных
 
Т.е. вот об этом и речь, раз
1) нельзя проверить подписку(влючено ли получение) на обезличенные сделки по инструменту, а также
2)  закрыть ранее открытую  (вручную через галочку/скриптом через  CreateDataSource) подписку на получение обезличенных сделок по  инструменту
возможно стоит данные функции ввести? ведь просто в терминале галочками это сделать возможно. он это позволяет.
Аналогично  с проверкой подписки на параметр из ТТП(isParamRequest). В терминале  получаемые параметры отмечены галочкой значит возможность такая опять же  имеется. добавьте данные функции в QLua, пожалуйста.


Касаемо
Цитата
Sergey Gorokhov написал:
Вы можете заказать данные и потом брать из AllTrade то что Вам надо. При этом не обязательно использовать именно OnAllTrade, можно например получать данные из самого источника (Функции O, H, L, C, V, T) или через свой колбек (SetUpdateCallback) или через SearchItems (к слову в ней можно назначить функцию со своими параметрами)
Мне нужно одинаковые параметры получать по разным бумагам(список изменяется). поэтому одна функция более чем подходит. и тики нужно получать в момент их прихода в терминал а не срезами, поэтому SearchItems не подходит.
Для SetUpdateCallback пока не понимаю что будет означать index т.к. все примеры для интервалов больше тика. это номер эл-та в таблице AllTrades, а не номер свечки как в документации написано? (меня только тиковые данные интересуют сейчас)

Цитата
Sergey Gorokhov написал:
что значит "удалить"? Пока не вызовите Close подписка не остановится.
Код
OnInit() 
  local ds = createDataSource('SPBFUT', 'RIZ8', INTERVAL_TICK)  
  ds:setEmptyCallback()
 end 
ds удаляется а подписка получается остается? хотя никто ее не использует после остановки этого скрипта.(таблиц в терминале не открыто). разве не логично удалять такие подписки. собсно это в дополнение к проверки на подписку. для таких моментов она и нужна. раз мы можем получать данные хотя никто их не обрабатывает. просто забыли закрыть ds. или не сохранили его в глобальной таблице луа. (что я имел ввиду под удалением).
динамический заказ тиковых данных
 
терминал v7.19
нужно динамически заказывать тиковые данные(обезличенные сделки) и удалять их из загрузки(когда перестали быть нужны)
желательно еще и список параметров сделки контролировать чтобы лишнее не загружать(как через таблицу всех сделок)
все это при закрытой таблице всех сделок.

пример:
допустим в произвольный момент нужно заказать подписку на
(SPBFUT, RIZ8) с параметрами
номер
код класса
код бумаги
дата
время
цена
кол-во

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

для заказа данных(тиковых) я так понял в этом случае единственным решением является
CreateDataSource(c_code, s_code, INTERVAL_TICK)
которая закажет сразу все параметры(и те которые мне не нужны)
и получать я их буду через OnAllTrade(новые)
вопросы
1) как то туда(в CreateDataSource) есть возможность сразу все параметры передать которые я хочу получать?
2) как проверять включена ли загрузка этого параметра? для стакана есть IsSubscribed_Level_II_Quotes. для обезличенных сделок не нашел.
3) как убрать подписку на какой-либо параметр[ы] обезличенной сделки (или бумагу целиком в частном случае если для параметров  не возможно)
4) нужно ли хранить таблицу ds полученную от CreateDataSource. если ее удалить перестанет ли идти подписка?
касаемо параметров бумаги (таблица текущих параметров)
5) почему нету функции isParamRequest (узнать заказан ли нужный мне параметр). Подписка/отписка же есть. или я ее тоже не нашел в документации. как проверять подписку?

вопросы наводящие тк лично мне не хватило функционала апи для заказа тиковых данных.
если кратко опишете то чем воспользоватся для решение проблемы описанной в первом обзаце можно не отвечать на остальное.
я просто не нашел в доках функций которые ее решают.
Глобальные таблицы Lua на C++
 
Цитата
Let_it_go написал:
Прошу подсказать какой аналог глобальной таблицы Луа для Си++
по индексу LUA_GLOBALSINDEX лежит адрес таблицы
Код
//ticker_list="GAZP,SBER,GMKN" -- остальное аналогично
lua_pushstring(L, "GAZP,SBER,GMKN");
lua_setfield(L, LUA_GLOBALSINDEX, "ticker_list");
Цитата
Let_it_go написал:
в какой части кода это объявлять?
в любой где есть lua_State.(как и в скрипте). Как вообще можно было придумать dllmain, если там вообще нету стейта луа.
например инициализация переменных в OnInit:
делается аналогично верхнему коду
Код
static int onInit(lua_State* L) {    
    lua_pushstring(L, "GAZP,SBER,GMKN");
    lua_setfield(L, LUA_GLOBALSINDEX, "ticker_list");
}

extern "C" __declspec(dllexport) int luaopen_plugin(lua_State *L) {
    lua_pushcfunction(L, onInit);
    lua_setfield(L, LUA_GLOBALSINDEX, "onInit");
    return 0;
}
советую почитать на досуге все ответы практически там есть
http://www.lua.org/manual/5.1/manual.html
Несколько общих вопросов по выполнению скрипта
 
Цитата
Дмитрий написал:
То есть мы получаем сигнал от коллбэка и обрабатываем его в майне. Допустим коллбэк "он квота" просигналил что в стакане что то изменилось и я в функции майн с помощью функции  "гетквоталевел" смотрю что там
Вообще так делать не рекомендую. колбек просигналит что есть данные. но мейн запрашивает данные позже. пока он их запросит стакан может вообще стать пустым и в мейте получите пустую таблицу.
Цитата
Дмитрий написал:
Отсюда вопрос - зачем нужно использовать коллбэк "он квота", когда я могу просто постоянно опрашивать стакан "гетквоталевелом"?
при постоянном опросе есть шанс пропустить данные между этими проверками(это касаемо стакана). при использовании колбека будет обработана вся информация.
если время обработки не существенно то используйте спокойно колбек.

если существенно и можно часть данных пропустить переносите обработку просто в main с опросом через getquotelevel2.
если существенно и нельзя данные пропускать: собираете эти данные в колбеке, запихиваете в таблицу обработки. шлете сигнал на обработку. в мейне ждете этот сигнал и обрабатываете таблицу.
Передать getQuoteLevel2 в dll
 
Павел Валин, да там все верно. ошибки такие с которыми dll точно бы не сбилдилась. старые мб остались. не видит функции с которыми длл билдится. ерунда вобщем

проверил на vs2017 все ок. ошибок с кодом выше 0.
Передать getQuoteLevel2 в dll
 
Просто думал вызов будет каким-то таким, не ошибка)
Код
static int forLua_SumArray(lua_State* L) {
    getQuote3(L);
    /* остальное */ 
}
Но вообще да. я код не компилил и не проверял на 100% правильность так что возможно гдето еще недочеты.
Если нужно этот код из lua вызывать то да, все функции которые пробрасываем в луа
Код
lua_CFunction=int(lua_State*)
что компилятор вам и указал во 2й строке скриншота
Передать getQuoteLevel2 в dll
 
Цитата
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); //чистим стек
}
Передать getQuoteLevel2 в dll
 
Цитата
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) https://github.com/SteveKChiu/lua-intf
2) https://github.com/jeremyong/Selene
Как их подключать и использовать описано в каждом из проектов. В основном это просто заголовочные файлы. все достаточно просто, скачиваете, делаете include и готово)Мне вот например синтаксис использования этих врапперов не зашел. Пришлось изучить их вдоль и поперек и сам апи луа, в итоге свой враппер реализовал) но это долгий путь. лучше готовое взять. selene вполне неплох.
ps. еще на форум выкладывали враппер на макросах. где и функции+таблицы из qlua уже описаны были. тоже можно попробывать, как вариант.
Что не так с функцией message??, проблемы с вызовом message из глобальной таблицы
 
Цитата
Павел Валин написал:
Это уже вопрос десятый. Мне просто интересно, почему все функции ведут себя ожидаемо работают, а эта глючит. У меня dll ка падает из за этого глюка))))
Разве она работает не ожидаемо?) 1й параметр - строка, а вы туда таблицу передаете.

и в isConnected тоже. Ненадо так делать) 2я функция не не падает потому что без параметров вызывается и просто игнорит то что вы ей там передаете.
Код
msg("msg test: "..iscon())
и все... копирование вообще не при делах.
luaL_len отсутствует в Lua 5.1
 
перебор таблиц можно делать не только по типу for(i=0;i<count;i++). кол-во элементов знать не обязательно.
Код
static int forLua_SumArray (lua_State* L) {
    double sum = 0; //при учете что на стеке таблица
    lua_pushnil(L); //nil
    while (lua_next(L, -2)) //след ключ+значение
    {
        double value = lua_tonumber(L, -1);        
        sum += value;
        lua_pop(L, 1); //чистим значение, оставляем таблица+послед. ключ
    }   
    lua_pop(L, 2); //2 или 1, не помню будет там посл. ключ или только таблица, вроде 2.
    lua_pushnumber(L, sum);
    return 1; 
}
Поместить колбек в dll
 
Приставов никаких не нужно. тк в функцию lua_pushcfunction передается  адрес функции. Можете называть ее как угодно(например "asd"). главное  сохранять сигнатуру lua_CFunction = int(lua_state*)
Когда пишете require "runfast" lua вызовет экспортируемую из dll функцию luaopen_runfast. Туда и вставляете код. После LuaL_openlib например(там у вас наверное регистрация доп. функций идет)
Поместить колбек в dll
 
примерно как то так. вроде в индексах не ошибся.
Код
static int onQuote(lua_State *L) {
    return 0;
}

extern "C" __declspec(dllexport) int luaopen_runfast(lua_State *L) {
    lua_pushvalue(L, LUA_GLOBALSINDEX); //на стек помещаешь глобальную таблицу
    lua_pushstring(L, "OnQuote"); //дальше строку с ключом таблицы
    lua_pushcfunction(L, onQuote); //дальше свою функцию
    lua_settable(-3); //помещаешь в таблицу по индексу -3, по ключю -2 значение в -1
    lua_remove(-1); //помойму дальше таблица останется на стеке можешь ее почистить.
    return 0;
}
Обращение к DataSource в main-потоке
 
Цитата
_sk_ написал:
В более сложных ситуациях подобного рода проблему полностью решил бы следующий подход, когда есть возможность запуска функции в потоке коллбэков с API типа следующего:
Делайте через ssort, работает стабильно.
Передаете в ssort таблицу на 2 элемента и заглушку которая вызывает пользовательский колбек. А там итерацию спокойно делаете любых данных.
разрабов в этом плане можно долго ждать, хотя мне бы тоже хотелось функционала из коробки (https://forum.quik.ru/messages/forum10/message28159/topic3225/#message28159)
Lua Dll на C++
 
Цитата
Андрей написал:
Похоже понял, однако уточните единственный ли это способ ? Хочется все варианты перебрать.
Код
  L_ptr  =  lua_newthread(L);
  
Так же скажите пожалуйста где бы взять список всех функций Луа и прочего которые в новом потоке запускаются, и какие в основном? Иначе говоря пренадлежность функция - поток (с точки зрения квика)
Ну ябы выбрал этот вариант. А все варианты... я незнаю для чего вам много потоков) принадлежность к потоку можно проверить GetCurrentThread()
все колбеки - основной поток квика. мэин - вам создали дополнительный, делайте там всю обработку.
у меня там крутиться очередь libuv, вполне удобно.
Lua Dll на C++
 
Стек глючить будет )
У вас будет 2 потока, каждый будет работать со своим стеком. (1 получите в функции main) 2й при вызове экспортируемой из длл функции.
Eсли паралельно будете писать в 1 стек(что можно), то там будет каша. вобщем для каждого потока используйте свой стек.
Если создаете еще какие то свои потоки дополнительно, то уже на сколько хватит фантазии, можно еще 1 стек создать и поток запустить из луа, например.
Потоки вооще я не советую внутри плодить. с синхронизацией потом намучаетесь.
Подвешивание info.exe через механизм межпоточного локинга
 
Алексей, Там скрипт - tcp сервер. Роботы к нему подключаются, получают обновления и текущие данные, транзакции отправляют. конектор вобщем.
Отсуда и требование получать списки с данными в произвольный момент времени. ( в момент подключения, а потом только обновления)

Доделал локинг через ssort. Обновления отправляю в очередь.

Вобщем все же уже есть (только в документации как всегда пусто).
Передаем в ssort таблицу на 2 элемента и заглушку которая вызывает пользовательский колбек. (интересно как сделать чтобы не передавать таблицу каждый раз?)
Почему бы не добавить функцию в qlua которая будет делаеть тоже самое но без заглушки?
res = scall( function, params...); 2 варианта (с ожиданием и без)
Подвешивание info.exe через механизм межпоточного локинга
 
Алексей, Спасибо. Все очень подробно. Но у Вас копия всех актуальных данных в памяти будет храниться, разве это хорошо?
У меня роботы торгуют по таблице всех сделок. Мне ее копию хранить не хотелось бы)
можно конешно взять еще бд под это дело подгрузить но зачем, ведь все данные уже есть в квике.
А говорите функционал с синхронизацией не нужен..

А про ф-цию seachitems подскажите?
она заранее данные для колбека подготавливает или также как цикл в примере через getitem их забирает и в колбек передает?
Хотя судя по тому что там обработка колбека тоже в мейне всеже для синхронизации это не подойдет.
я незнаю с чего вы против того чтоб добавляли такой функционал хотя он даже вам нужен. х2 по памяти. брр.. пусть делают, развивают. не нравиться такая концепция пусть другую дадут. проблема очевидная и все ее в меру возможностей решают внутри скриптов.
Подвешивание info.exe через механизм межпоточного локинга
 
Алексей,
1) В каждом колбеке будет уникальная ссылка на луа таблицу? Я думал квик изменяет данные а потом дает колбек на обработку пользователю. Чтобы быть на 100% уверенным что правильно вас понял:
Код
//обработка таких данных из мейна
    for (int i = 0; i < q.getNumberOf("orders"); i++)
    {
        //получаем таблицу, паралельно могут приходить колбеки
        lua::table t = q.getItem("orders", i); 
        main t --> (t.id = 1 , t.balance = 1)        
        //паралельно приходит колбек с такими пар-ми
        поток квика --> OnOrder (t.id = 1, t.balance = 0)

        int mybalance = t.balance
        а тут мы обрабатываем остаток(мейн поток). тут я считал что будет паралельный доступ к данным из 2х потоков. разве нет?
        квик записывает balance заявки а мы его в это время считываем. если квик всеже такое переваривает то что я получу при запросе из таблицы t.balance (0 или 1).
        тобишь обновит квик данные хранящиеся в таблице которую я уже получил или нет?
        
    }
Подвешивание info.exe через механизм межпоточного локинга
 
Michael Bulychev, Может быть проще добавить регистрацию пользовательский  колбеков которые исполняться будут в основном потоке квика? В порядке очереди..
Просто сейчас  тоже думаю как лучше решить похожую задачу(синхронизации потоков), такой небольшой функционал решил бы многие проблемы.

моя задача: в произвольный момент в мейне запрашивается список сделок или заявок. но пока он обрабатываеться могут прийти новые данные (или вообще очистка данных, когда новая сессия пошла). мне нужно сначала обработку завершить. Ставить крит. секцию на все колбеки и обработку данных как то не хочется.
метатаблица для OnInit
 
Хотелел именно так. Вся работа будет внутри dll. Скрипт делает только require.
Я переделал на передачу адреса объекта через lightuserdata, ничем не хуже только память чистить самому.

Дописав немного функционал убедился что созданный таким образом колбек(через userdata+metatable) также не вызывается будучи переданным в функцию SearchItems.
Ну и похоже везде эта проверка на то что в переменной функция.

Раз это не работает только для колбеков qlua, то просьба поправить qlua чтобы была такая возможность. (вызов пользовательский колбеков qlua как метатаблиц с __call)
метатаблица для OnInit
 
Цитата
Алексей написал:
Quik, скорее всего, перед вызовом пользовательских колбеков проверяет, чтобы в переменной (с зарезервированным именем колбека) хранилась ссылка именно на функцию.
В вашей реализации получается, что в переменной с зарезервированном именем OnInit хранится ссылка на таблицу. Вот Quik ее и не вызывает.
Что Вам мешает сделать просто OnI nit = a?
Пример только для проверки метатаблиц. Написал чтоб упростить вопрос.

Берем любую c-функцию(любая сигнатура). Создаем объект-обертку для нее на userdata.
К userdata добавляем метатаблицу с __call чтоб луа мог вызывать функцию(обычную int(lua_state*) в которой идет вызов обертки и далее уже нормальной функции.
Ну и __gc для ручного вызова деструктора у объекта-обертки.
Есть и другие варианты, через lightuserdata например. но тогда приходится в dll придется хранить список с указателями на эти обертки и чистить при выгрузке.

Вопщем я думал вариант с userdata и метатаблицами вполне стандартная возможность lua и странно что в qlua для колбеков это делать нельзя.
Я не так давно разбираюсь с этим языком, возможно я тут вообще не прав и нельзя какие то базовые функции так переопределять.(поправте если кто вкурсе, s_mike например говорит что это именно в qlua так)

Временно сделал конешно по другому но хотелось бы прояснить, это моя недоработка или в qlua.
метатаблица для OnInit
 
Код
function a(s)
    message(s)
end

Oni nit = {}
mt = { __call = a}
setmetatable(OnInit, mt)

--OnInit("a") 
Хотел на колбеки (например возмем OnInit) повесить метатаблицy и обнаружил что квик не хочет их вызывать.
Код выше в теории должен при старте скрипта вызвать a(). но он просто завершается
Но если принудительно вызвать OnInit("a") все работает. В чем подвох?
QUIK (версия 7.0.1.5), function OnTrade(trade), трехкратный вызов на одно событие.
 
Цитата
Sergey Gorokhov пишет:
В частности это UID, TRANS_ID а также набор флагов и ряд других специфичных параметров
Серверу чтобы проставить эти обновленные параметры приходится отправлять сделку несколько раз.
А зачем там эти параметры вообще были нужны? Ведь у сделки при первом ее приходе в терминал уже будет номер заявки а по заявкам эти параметры уже можно было узнать(были обновляемыми). И я так понимаю если по заявке будет несколько сделок каждую из них серверу нужно синхронизировать и в терминал будет прислано несколько обновлений на каждую сделку? Почему не оставили только для заявок, меньше нужно было бы информации повторной пересылать..
Страницы: 1
Наверх