static int forLua_MultTwoNumbers(lua_State *L) { // получаем первый и второй параметры вызова функции из стека с проверкой каждого на число double d1 = luaL_checknumber(L, 1); double d2 = luaL_checknumber(L, 2);
// помещаем в стек результат умножения lua_pushnumber(L, d1 * d2);
return(1); // эта функция возвращает одно значение }
// список реализованных в dll пользовательских функций static struct luaL_Reg ls_lib[] = { {"MultTwoNumbers", forLua_MultTwoNumbers}, {NULL, NULL} };
paluke написал: Библиотеку lua нужно указывать: ключики -L, -l
Я разместил в каталоге со всеми файлами файл lua54.lib, который взял из 1-го поста quik2dde.ru/viewtopic.php?id=18 и добавил опцию -Llua54.lib, сообщения с ошибками остались точно теми же, что и выше. Если, скажем, этот формат биб-ки понимает только микрософт и не понимает gcc, то почему линковщик ничего не говорит насчёт этого либ-файла?
Опять начал искать и наткнулся на стр. qna.habr.com/q/475056 Добавил по примеру оттуда в бат файл ключи -L. и -llua54 и получил наконец-то dll... Чертовщина...
И вместо int __declspec(dllexport) luaopen_mylib_funcs(lua_State *L) { luaL_newlib(L, ls_lib); return 1; }
надо вставить из исходника swerg
LUALIB_API int luaopen_luacdll(lua_State *L) { // эта функция выполнится в момент вызова require() в Lua-коде // регистрируем реализованные в dll функции, чтобы они стали дуступны для Lua // в Lua 5.1 и Lua 5.3 для этого предназначены разные функции #if LUA_VERSION_NUM >= 502 luaL_newlib(L, ls_lib); #else luaL_openlib(L, "luacdll", ls_lib, 0); #endif
Там, оказывается, дело было в имени: не luaopen_mylib_funcs, что я вбрал из другого примера, а luaopen_luacdll, поэтому первоначальную сишную функцию можно оставить, поменяв у неё имя:
int __declspec(dllexport) luaopen_luacdll(lua_State *L) { luaL_newlib(L, ls_lib); return 1; }
Спасибо, тов. swerg, за наше счастливое детство, меня сейчас интересует обмен данными между луа скриптом и длл на си. Кстати, вчера я запустил в квике ваш пример луа скрипта из 1-го поста: https://quik2dde.ru/viewtopic.php?id=329 Получил сообщение "C stack overflow". Может быть, с 2020 г. что-то поменялось в квике?
Serge123 написал: Спасибо, тов. swerg, за наше счастливое детство, меня сейчас интересует обмен данными между луа скриптом и длл на си. Кстати, вчера я запустил в квике ваш пример луа скрипта из 1-го поста: https://quik2dde.ru/viewtopic.php?id=329 Получил сообщение "C stack overflow". Может быть, с 2020 г. что-то поменялось в квике?
nikolz написал: покажите Ваш пример на C с ошибкой, исправлю.
Не понял: этот луа скрипт из предыдущего моего сообщения использует известную оболочку от swerg w32.dll, а работающий пример луа+длл на си, который транслируется gcc, на основе примера swerg, который собирался в VS, я получил ещё вчера.
Теперь меня интересует, как получать в длл таблицы от луа и разбирать их, напр., таблицу заявок и обезличенных сделок. Я несколько лет назад перешёл с Дельфи 7 на си под 64 бит и gcc, теперь неохота сидеть на 2-х стульях.
Кстати, если кто не знает, я автор книжки "Delphi и Turbo Pascal на занимательных примерах" (выходила в Питер-БХВ), а также нескольких других книжек, хотя, я программировал, как любитель, для развлечения, в основном писал для продажи англоязычные шареварные игры по своим идеям. А лет 15 назад я был монстром Perl regexp и написал о них лекции на intuit.ru и головоломную книжку, которая выносит мозги ногами вперёд (в связи с рекурсивными шаблонами и вообще). Понаходил в них и в Перле грубых ошибок, сообщал о них письмами Перл майнтайнерам, они их исправляли. К сожалению, эта узкая тема не приносит денег...
Судя по тому, что в указанном скрипте используется только w32 библиотека могу предположить, что вы используете данную библиотеку не с той версией Lua, в которой запускаете скрипты.
Не понятно мне только почему вы спрашиваете здесь, а не там :)
Serge123 написал: Я несколько лет назад перешёл с Дельфи 7 на си под 64 бит и gcc, теперь неохота сидеть на 2-х стульях.
dll для 64 бит Lua можно отлично делать на Lazarus или современных версиях Delphi, которые научились компилить под x64. Удобно и приятно я бы даже сказал.
Цитата
Serge123 написал: Теперь меня интересует, как получать в длл таблицы от луа и разбирать их, напр., таблицу заявок и обезличенных сделок.
Информации об API в Lua очень много, почитайте. Хотя, если честно, я бы рекомендовал писать и отлаживать алгоритмы на Lua. Это намного проще. И только если будут выявляться какие-то узкие места в производительности - что-то выносить в dll. Сидеть копаться в Си-коде для работы с таблицами Lua - достаточно занудно. Сложного там ничего нет, API очень простое и понятное, но надо постоянно помнить про все нюансы; к тому же то, что в Lua пишется кратко просто и естественно (типа обращения к таблице по ключ) в Си шном API делается в несколько "команд". Короче краткости там и наглядности - никакой. Так то не совсем мне понятно зачнем это. Ну кроме выпендрёжа "а у меня весь робот на Си!".
Serge123 написал: Теперь меня интересует, как получать в длл таблицы от луа и разбирать их, напр., таблицу заявок и обезличенных сделок. Я несколько лет назад перешёл с Дельфи 7 на си под 64 бит и gcc, теперь неохота сидеть на 2-х стульях.
Я согласен с тем, что выше написал swerg. От себя добавлю: возможно, для вас окажется полезным сайт https://quikluacsharp.ru/ , на котором есть много чего интересного, в том числе "КРАТКАЯ СПРАВКА ПО ЯЗЫКУ LUA.PDF", написанная мною. В ней есть описание трансляции C++ dll для Lua, а также краткое описание C-API Lua.
swerg написал: Хотя, если честно, я бы рекомендовал писать и отлаживать алгоритмы на Lua. Это намного проще. И только если будут выявляться какие-то узкие места в производительности - что-то выносить в dll.
А что вы скажете об этих рассуждениях о qlua, которые я только что увидел на smart-lab.ru/blog/922044.php === Каждого, кто собирается программировать на QLua, должен сильно волновать ответ на следующий вопрос: стоит ли изучать Lua или воспользоваться некоей библиотекой (как пример QuikSharp + QuikPy) и в дальнейшем писать свои программы на другом ( скажем мягко — менее экзотическом) языке (Python, C#, С++ и т.п.). Когда разработчики Квика встраивали Луа в Квик, это был (Луа 5.1 х32) популярный язык с огромным количеством всяких разных библиотек, компилятором (LuaJIT), своим менеджером пакетов и большим комьюнити. Потом прошло некоторое количество времени, Луа в Квике изменился на Луа 5.4 х64 и все достоинства его превратились в тыкву. Оказалось, что это практически умирающий ( утопающий) язык, поддержка которого — дело рук самих утопающих. Кто-то успел ухватить тренд и быстренько переписал все на Python и остался конкурентноспособен ( хороший пример Torch -> PyTorch ), кто-то все проспал и утонул (ну или еще пока барахтается). В связи с выше сказанным, очень хотелось бы выяснить, так сказать на берегу, стоит ли свеч QLua, или можно построить такого же стабильного и быстрого робота на другом языке. === Простых алгоритмов или несколько роботов запустить, это всё будет вполне устойчиво работать. Что-то более сложное (сотни стратегий торговых, постоянная оптимизация под рынок, с оперативным управлением и ротацией роботов) действительно пишутся уже в связке или полностью на других языках. ===
swerg написал: Хотя, если честно, я бы рекомендовал писать и отлаживать алгоритмы на Lua. Это намного проще. И только если будут выявляться какие-то узкие места в производительности - что-то выносить в dll.
А что вы скажете об этих рассуждениях о qlua, которые я только что увидел на smart-lab.ru/blog/922044.php === Каждого, кто собирается программировать на QLua, должен сильно волновать ответ на следующий вопрос: стоит ли изучать Lua или воспользоваться некоей библиотекой (как пример QuikSharp + QuikPy) и в дальнейшем писать свои программы на другом ( скажем мягко — менее экзотическом) языке (Python, C#, С++ и т.п.). Когда разработчики Квика встраивали Луа в Квик, это был (Луа 5.1 х32) популярный язык с огромным количеством всяких разных библиотек, компилятором (LuaJIT), своим менеджером пакетов и большим комьюнити. Потом прошло некоторое количество времени, Луа в Квике изменился на Луа 5.4 х64 и все достоинства его превратились в тыкву. Оказалось, что это практически умирающий ( утопающий) язык, поддержка которого — дело рук самих утопающих. Кто-то успел ухватить тренд и быстренько переписал все на Python и остался конкурентноспособен ( хороший пример Torch -> PyTorch ), кто-то все проспал и утонул (ну или еще пока барахтается). В связи с выше сказанным, очень хотелось бы выяснить, так сказать на берегу, стоит ли свеч QLua, или можно построить такого же стабильного и быстрого робота на другом языке. === Простых алгоритмов или несколько роботов запустить, это всё будет вполне устойчиво работать. Что-то более сложное (сотни стратегий торговых, постоянная оптимизация под рынок, с оперативным управлением и ротацией роботов) действительно пишутся уже в связке или полностью на других языках. ===
см басню Крылова "Лиса и виноград" --------------------- QLua - это не язык программирования, а библиотека написанная на СИ с интерфейсом VMLua для взаимодействия с терминалом QUIK.
Lua как и Питон - скриптовый язык. И не существует железа, которое может исполнять непосредственно байт-код. Байт-код всегда исполняется функциями на СИ. ------------------ Никто не мешает писать на Питон, если Вам это нравиться. Но Питон - это тормоз еще тот. -------------- Что же касается Torch, то там еще прикольнее, так как все библиотеки линейной алгебры (BLAS) написаны на фортране. ============== Для справки еще есть LuaJit и Terra , в которых реализованы параллельные вычисления.
Кстати, хотел найти работающий пример для разбора таблиц в длл, взял с этого сайта код quikluacsharp.ru/qlua-c-cpp-csharp/primer-realizatsii-funktsii-obratnogo-vyzova-onalltrade-vnutri-dll/ а там полная ерунда: вместо lua_pushcfunction написано lua_pushcclosure. Да и luaL_openlib уже устарела и здесь не нужен также и новый её вариант для луа 5.4. Потерял много времени...
Кстати, хотел найти работающий пример для разбора таблиц в длл, взял с этого сайта код quikluacsharp.ru/qlua-c-cpp-csharp/primer-realizatsii-funktsii-obratnogo-vyzova-onalltrade-vnutri-dll/ а там полная ерунда: вместо lua_pushcfunction написано lua_pushcclosure. Да и luaL_openlib уже устарела и здесь не нужен также и новый её вариант для луа 5.4. Потерял много времени...
Serge123, уже говорил, но повторю, что я юзаю библиотеку sol3 , чтобы писать на C++ вместо Lua и почти полностью забыть о стеке и Lua API. Библиотек под Lua маловато, критика в цитате обоснована. А python, да, медленный и изначально не параллельный.
Поясните, почему в таблицах Квика orders, trades, ... переменная flags, хранящая битовые флаги, имеет тип NUMBER (что в переводе на C значит double), а не INTEGER? Ведь тип LUA_NUMBER это double (64 бита) LUA_INTEGER это long (64 бита) (под 64-битовой ОС) Эти флаги в C правильно получать функцией lua_tointeger или lua_tonumber? Вроде бы работает и то и это... Тот же вопрос насчёт поля qty. И почему в подтаблице datetime поля также имеют тип NUMBER, а не INTEGER? Они что, внутри Lua имеют тип double?
Если на C переменной, в которую читаю flags, присвоить тип LUA_NUMBER, то транслятор выдаёт ошибку: должен быть тип целого числа.
Serge123 написал: Поясните, почему в таблицах Квика orders, trades, ... переменная flags, хранящая битовые флаги, имеет тип NUMBER (что в переводе на C значит double), а не INTEGER?
Потому что в Lua5.1, которая изначально была прикручена в quik, тип number мог быть либо int, либо double. В зависимости от параметров сборки. Одновременно int и double там не существовало. Для QLua выбрали вариант сборки с double, по понятным причинам.
Serge123 написал: Вернее, транслятор ошибку не выдаёт, но для выделения флагов в C придётся преобразовать тип flags к (u)int64_t, что выглядит не очень красиво...
Это половые трудности того, кто зачем-то пытается делать роботов на Си вместо Lua.
Хочешь по-взрослому - и страдай тогда по-взрослому, не плачь ;)
Насколько я понял, lua_tonumber и lua_tointeger это одно и то же и ничего она не преобразовывает, просто переписывает с вершины стека в заданную переменную 8 байтов?
И ещё хотел спросить: неужели с рублями и копейками работают в формате double? В этом случае при расчётах может накапливаться ошибка. Как я помню, в фин. расчётах рубли и копейки хранили в виде строк, напр. "123.456000".
Serge123 написал: Насколько я понял, lua_tonumber и lua_tointeger это одно и то же и ничего она не преобразовывает, просто переписывает с вершины стека в заданную переменную 8 байтов?
И ещё хотел спросить: неужели с рублями и копейками работают в формате double? В этом случае при расчётах может накапливаться ошибка. Как я помню, в фин. расчётах рубли и копейки хранили в виде строк, напр. "123.456000".
lua_tonumber и lua_tointeger в версиях от 5.3 - это разные форматы. double и long.
nikolz написал: lua_tonumber и lua_tointeger в версиях от 5.3 - это разные форматы. double и long.
А в Lua 5.4 одинаковые? Как это узнать?
Я для интереса написал в длл на си "ядерную триаду": обработчики OnAllTrade и OuQuote + getQuoteLevel2. Постарался, чтобы работало как можно быстрее. В примерах, которые я видел, написано не так оптимизированно, как у меня. Неплохо было бы как-то сравнить скорости с моими аналогичными обработчиками на Lua...
Возникли такие мелкие вопросы:
1. Скрипт, который работает с этой длл, начинается так:
Я где-то увидел, что таким путём можно длл помещать в папку со скриптами вместо корневой папки Квика. Но почему-то при первом запуске скрипт не находит этой длл в папке со скриптами, поэтому длл приходится помещать в корневую папку. При последующих запусках скрипта длл можно удалить из корневой папки и размещать в папку со скриптами, это работает. Кто может объяснить этот эффект и сказать, как это исправить?
2. Можно ещё быстрее работать со стеком Луа при обработке полученных таблиц? Например, можно ли быстрее получить из таблиц bid и offer значения price и quantity (по 20 штук каждых)?
3. Я после вызова функций QLua из длл не очищаю стек, потому что он после этого вроде бы становится мусором для уборки. Достаточно следить, чтобы стек не превышал 20 элементов. Это верно?
4. В аналогичном скрипте на Луа я накапливаю информацию в переменной-строке о сделках и стаканах и после достижения, скажем, 10 Мб дописываю её в файл и потом присваиваю этой переменной пустую строку. При этом каждый раз память для неё освобождается сборщиком мусора и затем выделяется и довыделяется много раз при её заполнении информацией. А выделение памяти не быстрый процесс. На си такой проблемы нет. Можно ли на Луа работу с этим буфером вывода сделать быстрее?
5. В своём аналогичном скрипте на Луа при выводе содержимого стакана в переменную я беру текущее время через os.sysdate, она даёт даже мкс, откуда у неё такая точность? Может, лучше как-то получать время сервера брокера, это будет точнее? Кстати, на этом форуме ещё в 2015 г. просили с содержимым стакана передавать время с сервера (биржи?), когда было изменение, но почему это не сделали? На си я для этого получаю время через GetSystemTime, там только мс, приходится дописывать к ним справа 000, чтобы был формат с мкс, как выдаёт OnAllTrade. С этим ничего нельзя поделать?
Serge123 написал: Уточнение: на си я получаю текущее время моего ПК через GetLocalTime, три часа разницы...
я же написал : " в версиях от 5.3 " т е и в 5.3 и 5.4 и дальше - разные. ------------------- Для измерения времени работы напишите две ф-ции на си в DLL типа
квант времени 0.1 мкс. ===================== Я синхронизирую компьютер с сервером точного времени. Погрешность синхронизации не более 10 ms. Можно в скрипт принимать с сервера точного времени. ---------------------- Еще учитывайте, что квант времени задачи в винде это 10 ms. =================== Обработку колбеков выполняю выношу в main и в других потоках из пула потоков. Поэтому все колбеки у меня близнецы:
Код
function OnTransReply(t) tprm[#tprm+1]={1,t}; nkevent.Set(event); end
function OnOrder(t) tprm[#tprm+1]={2,t}; nkevent.Set(event); end
function OnStopOrder(t) tprm[#tprm+1]={3,t}; nkevent.Set(event); end
function OnTrade(t) tprm[#tprm+1]={4,t}; nkevent.Set(event);end
function OnParam(c,s) tprm[#tprm+1]={14,{c,s}}; nkevent.Set(event); end
...
Serge123 написал: 4. В аналогичном скрипте на Луа я накапливаю информацию в переменной-строке о сделках и стаканах и после достижения, скажем, 10 Мб дописываю её в файл и потом присваиваю этой переменной пустую строку. При этом каждый раз память для неё освобождается сборщиком мусора и затем выделяется и довыделяется много раз при её заполнении информацией. А выделение памяти не быстрый процесс. На си такой проблемы нет. Можно ли на Луа работу с этим буфером вывода сделать быстрее?
Накапливайте строки в таблице. Перед дампом делайте table.concat. Реализация table.concat в исходниках lua такова, что там одно выделение памяти на сумму длин строк в таблице. Но в Lua я не парюсь и юзаю PrintDbgStr + DebugView++.
Цитата
Serge123 написал: 5. В своём аналогичном скрипте на Луа при выводе содержимого стакана в переменную я беру текущее время через os.sysdate, она даёт даже мкс, откуда у неё такая точность?
Serge123 написал: 1. Скрипт, который работает с этой длл, начинается так:
У меня такой код никогда не приводил к описанной ошибке, пока lua_share.dll была в папке со скриптом:
Код
package.cpath = getScriptPath() .. "/?.dll"
sh = require "lua_share"
Но в результате мне больше нравится положить все dll'ки в одну папку так:
Код
c:\QUIK_installs\
lib\
lib\lua\
lib\lua\5.3\ тут dll для 5.3
lib\lua\5.3\vcl\ и тут тоже
lib\lua\5.4\ а тут для 5.4
lib\lua\5.4\vcl\ и тут
QUIK_BCS\
QUIK_BCS\info.exe квик тут
QUIK_BCS\lua\ скрипты тут и в подпапках юзают правильную версию dll из lib/5.* без возни с package.cpath, и умеют require "name" для правильных версий share/5.*/name.lua
QUIK_BCS\lua\lua_share_examples_5.4\
QUIK_BCS\lua\MA server\
QUIK_BCS\lua\MA server\share\
QUIK_BCS\lua\История позиций\
QUIK_BCS\LuaIndicators\
QUIK_megabroker\
QUIK_megabroker\info.exe а тут другая установка квика, но я так не пробовал ещё, поэтому и другие скрипты не перенёс изнутри первой установки квика
...
share\
share\lua\
share\lua\5.3\ тут общедоступные lua модули для 5.3
share\lua\5.4\ тут общедоступные lua модули для 5.4
Такая организация позволяет не возиться с package.path, package.cpath, не иметь лишних dll в корневой папке квика и потенциально юзать в разных установках квика скрипты из одной папки.
Это не то: GetSystemTimePreciseAsFileTime выдаёт время в UTC (число 100 нс интервалов с 1 января 1601 г. по текущее время). Теперь надо получить из него часы, минуты, секунды и микросекунды с десятыми с часами для локального времени. Я уже почти написал программку для этого перевода, но вроде бы должна быть готовая в какой-нибудь библиотеке для Си...
Serge123 написал: Это не то: GetSystemTimePreciseAsFileTime выдаёт время в UTC (число 100 нс интервалов с 1 января 1601 г. по текущее время). Теперь надо получить из него часы, минуты, секунды и микросекунды с десятыми с часами для локального времени. Я уже почти написал программку для этого перевода, но вроде бы должна быть готовая в какой-нибудь библиотеке для Си...
Вы можете получать время до секунды обычными функциями луа. --------------------- Для получения числа миллисикунд с шагом 0.1 мкс выкладываю функцию на C for Lua, которую надо добавить в DLL для Lua:
Код
static int ms(lua_State *L){
GetSystemTimePreciseAsFileTime(&UTC);
LARGE_INTEGER z; z.LowPart=UTC.dwLowDateTime;
z.HighPart = UTC.dwHighDateTime;
long ns=z.QuadPart%10000000ULL;
double x=((double)ns)/10000.;
lua_pushnumber(L,x);
return 1; }
В результате получим следующее
Код
Tue Jan 9 10:57:47 2024
944.631400
Tue Jan 9 10:57:47 2024
944.667900
Tue Jan 9 10:57:47 2024
944.704500
Tue Jan 9 10:57:47 2024
944.741300
Tue Jan 9 10:57:48 2024
45.804000
Tue Jan 9 10:57:48 2024
45.864200
Tue Jan 9 10:57:48 2024
45.921100
Tue Jan 9 10:57:48 2024