Владимир,Вы по какой причине ко всем докапываетесь со своими "единственными верными", но бесполезными советами? Не нравится луа, пиши на си. Не нравится квик, уйди на другой терминал, терминалов много. Куда не глянь, в каждой теме успел засветится с одним и тем же по сути. Хотя глухому навряд ли можно все это объяснить. Человек, который утверждает, что не интересуется мной АБ-СО-ЛЮТ-НО, но при этом отвечает на мои сообщения, как минимум врун. Не интересуешься пройди мимо.
Владимир написал: Александр, Лапуль, я всегда спокоен. И на кнопки попадаю на те самые. Судя по обсуждению, в отличие от подавляющего большинства остальных участников форума. Ибо у меня ОДИН скрипт - к тому же, написанный на ЧИСТОМ Lua, а потому прекрасно работающий НА ВСЕХ (постоянно меняющихся) версиях софта.
Есть больные, которые ни когда не признаются, что они больные и откажутся принимать таблетки. P.S. Теперь все должны делать, как ты? Это же признак болезни, дед?
Anton,Ни во всех версиях квика в луа библиотеке есть luaI_getextraspace swerg, Первый способ: сделать 2 разные библиотеки для разных версий DLL. Второй способ: сохранить указатели для каждой версии Lua DLL (сделать struct с указателями). И в колбеках проверять, в какой версии Lua запущена библиотека и брать указатели (как вы и писали).
swerg,Так оно не работает, если запустить два разных скрипта, но с одной DLL. У меня при этом остановка одного скрипта, останавливается второй скрипт. Частично в том, чтобы использовать openlib и каждый раз переименовывать библиотеку.
Виталий, Вам дали путь решения вашей проблемы, а вы вместо задавания вопросов, начинаете выступать, так не буду, сяк не буду. У вас проблемы вы ее и решайте. Информации больше, чем достаточно. Вопрос заключается в том, чтобы вызвать из неуправляемой среды управляемый код? Луа и QLua тут не причем. Примерный путь решения описан так.
Код
unk := nil;
OleCheck(CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, unk));
FMetaHost := unk as ICLRMetaHost;
unk := nil;
OleCheck(FMetaHost.GetRuntime(PWideChar(AClrVer), IID_ICLRRuntimeInfo, unk));
FRuntimeInfo := unk as ICLRRuntimeInfo;
FRunTimeInfo.SetDefaultStartupFlags(GetLoaderFlags(ConcurrentGC, LoaderFlags), nil); //Установим загрузочные флаги
OleCheck(FRuntimeInfo.IsLoadable(isLoaded)); //Проверяем на загружена ли сборка
if not isLoaded then
raise EOleError.CreateFmt(ECRLNotLoaded, [AClrVer]);
unk := nil;
OleCheck(FRuntimeInfo.GetInterface(CLASS_CorRuntimeHost, IID_ICorRuntimeHost, unk));
FDefaultInterface := unk as ICorRuntimeHost;
FDefaultInterface.Start;
iDomain := iHost.DefaultAppDomain;
RawAssembly := LoadAssemble('TestCrl.dll'); //Загрузка сборки в VarArray
&type := iAssm.GetType_2(typeName); //Получаем тип класса
ov := &type.InvokeMember_3('ctor', BindingFlags_CreateInstance, nil, null, nil); //Создаем класс
if VarSupports(ov, ITest, test) then //Получаем интерфейс
test.ShowMessage('Hi World'); //Вызываем функцию интерфейса
....
//Обнуляем интерфейсы
Владимир написал: Александр, Лапуль, я уже говорил, что с раннего детства терпеть не могу распальцованных дураков. Гнутых пальцев я тут уже видел выше крыши, а программистов - полтора человека, и уж Вы никоим образом к ним не относитесь. Так что НЕ ВАМ что-то тут вякать про "пора менять работу". И говорил уже тыщу раз: задачи организации торговли настолько элементарны, что решаются ЛЮБЫМ способом. В частности, на чистом Lua, без всего этого маразма с обилием языков, библиотек, версий и прочей лабуды.
Прими таблетки, а то только можешь ногами стучать, да желчь испускать.
Александр В луа 5.4 lua_version просто возращает версию луа 504 не зависимо от того, для какой версии LuaState. Но в целом можно попробовать пошаманить с этим делом.
Ниже вы приводите результаты ваших исследований, за них вам спасибо.
Засада с этим красивым автоматическим определением будет вот где. (предположим что в принципе оно у нас заработало и нам повезло - бинарно интерфейсы совпали) Если пользователь запустит одновременно два скрипта, использующих такую волшебную библиотеку - ему явно не повезёт. Потому что указатели на функции в Lua53.dll / Lua54.dll вы явно храните в глобальных переменных, т.е. в каждый момент времени в них фактически указатели на какую-то одну версию Lua. И даже если разнести указатели в 2 разные структуры по версиям Lua - то придётся в начало каждой интерфейсной функции вставлять хитрую проверку версии переданного стека, а потом еще хитро переключаться на соответствующую версию структуры указателей на функции Lua-API в рамках этой функции, вызванной внутри библиотеки.... Как-то это уже слишком, по-моему.
Я вас не понял. LuaState разный для версии Lua53 и Lua54, поэтому можно определить хаком версию луа. Я делаю такую проверку, если определяю, что у меня Lua53.dll и Lua54.dll одновременно находятся в памяти. У меня разные скрипты работают одновременно с разными версиями Lua. В целом способ рабочий, пока другого решения нет. Ждем ответа разработчиков.
Александр написал: Я изучил структуры lua_State для луа 5.3 и 5.4 и они различны. Если поле status <> 0, то это lua5.3, иначе lua5.4.
Тоже в эту сторону смотрел, показалось ненадежным. Там есть еще одно интересное место, если уже привязываться к версии и немного хачить: к стейту прицеплена юзердата, сам квик по ней версию и определяет (несколько запутанным способом, я не понял, как именно). Получить можно с помощью экспортируемой luaI_getextraspace или (раз уж хачить) просто как ((char *)pstate) - 8, оно во всех версиях луа одинаково. А уж дальше порыться там.
Этот способ подходит только для определения версии 5.3 или 5.4. С луа 5.1 status = 0. Поэтому чисто ограничился этим. lua_getextraspace - опять же надо загружать какую-то из этих DLL, а вот LuaState разный для разных версий.
Владимир написал: У меня опыт работы 30+ лет, и я не могу "связать 3 интерфейса, чтобы запустить сборку". Более того, считаю это клиническим маразмом, так что сделал логику на Lua, интерфейс на Lua и всё остальное тоже на Lua.
Тебе мамка сиську в детстве не давала? И теперь ты лезешь во все темы со своим мнением. Может другим способом задача автора не решается.
swerg написал: Фига себе! Александр , спасибо вам большое!!
Сложно это все, проще через CLRCreateInstance, ICLRMetaHost, ICLRRuntimeInfo, ICorRuntimeHost
Смотрел, не понял, как это сделать и куда всунуть чего в моей либе сишной. Да и есть ли смысл, уже не знаю даже. Лучше, наверное, все-таки делить ответственность: логика на C++, интерфейс на C#. За примеры спасибо, изучу, вероятно применю что-то в будущем.
Сейчас сделал загрузку сборки из квика на lua api данным способом. Все хорошо работает. Проверенно.
Владимир написал: Александр, Тут всем пора менять работу - программисты вымерли. Логика на C++, интерфейс на C#, форум по Lua...
У меня опыт работы 30+ лет, и я не могу "связать 3 интерфейса, чтобы запустить сборку". Более того, считаю это клиническим маразмом, так что сделал логику на Lua, интерфейс на Lua и всё остальное тоже на Lua. ::
Опять глюки начались, прими уже таблетки и успокойся.
function FindLuaLibrary(LuaState: lua_State) : Boolean;
type
TLua_version_52 = function (L : lua_State) : Plua_Number; cdecl;
TLua_version_54 = function (L : lua_State) : lua_Number; cdecl;
PLuaState = ^TLuaState;
TLuaState = record
next: Pointer;
tt: Byte;
marked: Byte;
case byte of
53: (
nci53: Word;
);
54: (
status: byte;
allowhook: byte;
nci54: Word;
);
end;
function IsModuleLoaded(const ModuleName : String; var Handle : THandle) : Boolean;
begin
Handle := GetModuleHandle(PChar(ModuleName));
Result := Handle > 0;
end;
var Handle53 : THandle;
Handle54 : THandle;
version52: TLua_version_52;
version54: TLua_version_54;
begin
Result := IsModuleLoaded(LuaLibName53, Handle53) and
IsModuleLoaded(LuaLibName54, Handle54);
if not Result then
Exit;
try
if PLuaState(LuaState)^.status <> 0 then begin
//Проверим версию для lua5.3
version52 := GetProcAddress(Handle53, 'lua_version');
Result := (@version52 <> nil) and (version52(LuaState)^ = LUA_VERSION_NUM_53);
if Result then
LuaLibName := LuaLibName53;
end
else begin
//Проверим версию для Lua5.4
version54 := GetProcAddress(Handle54, 'lua_version');
Result := (@version54 <> nil) and (version54(LuaState) = LUA_VERSION_NUM_54);
if Result then
LuaLibName := LuaLibName54;
end;
except
Result := False;
end;
end;
Виталий написал: Смотрел, не понял, как это сделать и куда всунуть чего в моей либе сишной. Да и есть ли смысл, уже не знаю даже. Лучше, наверное, все-таки делить ответственность: логика на C++, интерфейс на C#. За примеры спасибо, изучу, вероятно применю что-то в будущем.
Если вы у вас опыт работы 10+ лет и вы не можете связать 3 интерфейса, чтобы запустить сборку и вас забанили в гугле. То вам пора менять работу.
АлександрНе подходит, т. к. в Lua 5.4 lua_version просто возвращает номер версии, а при передаче в luastate от Lua 5.4 в функцию lua_version от Lua 5.3 происходит ACCESS_VIOLATION.
А, ну и славно, вот и проверили, бинарно не совместимы версии.
Я немного не понял: я вам чем-то обязан, что вы позволяете себе писать именно так? Я писал выше, вариант один: две разные dll для разных версий Lua. Как их загружать в скрипт при условии, что пользователь может выбрать одну из версий Lua - не знаю. Видимо раскладывать dll разных версий Lua по разным папкам и с путями в скрипте играться в зависимости __VERSION, или имена разные давать dll для разных версий Lua и опять же подгружать нужную библу.
Вы мне ничего не должны. Странно, что вы так на этот вопрос отреагировали. Это скорее вопрос к разработчикам. Нагородили кашу, пусть разбирают. Я уже поддержку lua53 и lua54 реализовал. Сейчас осталось понять какую версию lua dll подсовывать. Все это не решает вопрос, потому что не понятно, какую версию луа брать.
Чтобы использовать lua_version надо загрузить нужную dll. Возникает вопрос какую версию dll брать?
Вы не сделаете динамическую загрузку DLL нужной версии. Во-первых потому, что нет интерфейса для понимания того, на какой Lua-стек вам передали указатель, а во вторых потому, что вполне вероятно (но это надо дотошно проверять), что отдельные интерфейсные структуры в 5.3 и 5.4 версиях - разные. И в этом случае вы просто не сможете сделать бинарно совместимые версии dll. Вот и остаётся нам максимум - это проверить, что dll собрана под ту версию Lua, для которой она собрана. Фиговую какашку нам подсунули разработчки QUIK, да. Ведь фактически нельзя теперь просто положить dll в каталог с QUIK и использовать её спокойно, ведь в зависимости от версии Lua, заданной для скрипта, dll либо поедет, либо не поедет.... Да ужж...
Цитата
В луа 5.4 lua_version просто возращает версию луа 504 не зависимо от того, для какой версии LuaState.
Эту фразу не понял. Если вы скомпилировали вашу библиотеку (или динамически подгрузили) lua54.dll - то она вам и вернёт всегда 504 из lua_version. Т.к. эта функция просто возвращает вкомпилированную константу (см. исходники), на LuaState она не смотрит.
Я динамически подгружаю нужную luaxx.dll в зависимости от версии квика. У меня библиотека на все версии луа.
Александр написал: При чем здесь _VERSION, я использую Lua Api?
При том, что вы можете прочитать значение глобальной переменной _VERSION.
Ну а дальше уже из серии "Давай я погуглю за тебя". Ну ок, мне тоже пригодится, так что 1:1.
1) lua_version(lua_State *L) 2) void luaL_checkversion_ -- вызывает luaL_error(), если версия не та, что требуется.
Не подходит, т. к. в Lua 5.4 lua_version просто возвращает номер версии, а при передаче в luastate от Lua 5.4 в функцию lua_version от Lua 5.3 происходит ACCESS_VIOLATION. Еще варианты?
Александр написал: При чем здесь _VERSION, я использую Lua Api?
При том, что вы можете прочитать значение глобальной переменной _VERSION.
Ну а дальше уже из серии "Давай я погуглю за тебя". Ну ок, мне тоже пригодится, так что 1:1.
1) lua_version(lua_State *L) 2) void luaL_checkversion_ -- вызывает luaL_error(), если версия не та, что требуется.
Чтобы использовать lua_version надо загрузить нужную dll. Возникает вопрос какую версию dll брать? В луа 5.4 lua_version просто возращает версию луа 504 не зависимо от того, для какой версии LuaState. Но в целом можно попробовать пошаманить с этим делом.
Виталий написал: И что не так? В этой либе мне нужно использовать CLR, там будут формы. Как сам факт поддержки CLR (без каких-либо вызовов) влияет на выгрузку библиотеки?
Как минимум - вот оно коренное отличие вашей DLL от моей, а вовсе не версия QUIK. Ну и видимо передавайте привет .NET и особенностям ее работы.
Цитата
Виталий написал: (без каких-либо вызовов) влияет на выгрузку библиотеки?
Вы может и не вызываете, но раз хотите .NET - оно там очень могуче напрягается, чтобы вам его предоставить. Вам наверное будет не сложно пока отключить использование .NET и проверить.
Пока не сложно. Проверил. Без NET выгружается. Другой вопрос: как обеспечить выгрузку с NET, не знаете? Полагаю, спрашивать разрабов квика бесполезно про это...
Способов подключения сборок на си++ как минимум 2: 1. это использовать управляемый код. 2. Использовать интерфейсы и самостоятельно загружать сборки. Тот и другой способ гуглится. Но возможно стоит начать вот CoInitializeEx и CoUninitialize. Но я бы советовал сделать отдельное приложение на .net и передавать туда данные, например по сети.
Не, приложение с передачей данных это такое себе. Это как C# приложение с коннектором C++ - древняя тема и такая же нестабильная. Я пробовал ее году в 2015 еще, че-то не зашло. Я тогда ушел на LUA чистый и его хватало. Сейчас появилась потребность в более нормальном языке, чем LUA и я нашел вариант с подключением библиотеки. Я продолжил бы писать на C# (его знаю, а С++ нет), но проблема в том, что на шарпе нет нормального способа сделать либу. Есть какой-то полукостыльный и он мне не понравился и результат сомнительный. Интерфейсы на чистом Win API тоже не осилил как-то. Вот прикрутил CLR, но оно вон че оказалось. Буду еще смотреть, что дальше делать, но куча посредников между биржей и моим алгоритмом - это печаль и зло. Хочу поменьше, чтоб стабильнее и быстрее было.
Сделай секцию экспорта в C# библиотеке: сначала дезасемблировать, потом прописывать флаги и секции. Я специально программу написал, которая такое делает. И можно использовать LoadLibrary на стороне луа и все другие вкусняшки.
Вообще не понял. Как я читал, у C# проблема с экспортом функций и чтобы они были доступны - нужно ставить какую-то приблуду, которая работает только в английской локали. Ты про это или про что-то другое говоришь?
В С# проблема с экспортом функций в том, что MS не хочет ее реализовывать. Практических проблем нет. Ставить приблуду не обязательно. Надо: 1. ildasm.exe декомпилировать код. 2. В тексте кода найти все нужные функции и вставить .export[{номер функции}]. Можно использовать ObfuscationAttribute для определения нужных функций. 3. ilasm.exe скопилировать код в бинарник. В 64 битном режиме поправить установить флаг .corflags 0x00000002 Утилиту которая такое делает можно написать за один вечер. Читай книгу Serge Lidin ".Net IL Assembler"
Александр написал: Как понять в каком окружении запущен скрипт?
_VERSION
При чем здесь _VERSION, я использую Lua Api? При загрузке у меня есть только LuaState и мне нужно подключиться к нужной dll (lua53.dll или lua54.dll), при этом обе dll загружены в память.
Александр, Сделай секцию экспорта в C# библиотеке: сначала деасемблировать, потом прописывать флаги и секции, потом обратно скомпилировать. Я специально программу написал, которая такое делает.
Виталий написал: И что не так? В этой либе мне нужно использовать CLR, там будут формы. Как сам факт поддержки CLR (без каких-либо вызовов) влияет на выгрузку библиотеки?
Как минимум - вот оно коренное отличие вашей DLL от моей, а вовсе не версия QUIK. Ну и видимо передавайте привет .NET и особенностям ее работы.
Цитата
Виталий написал: (без каких-либо вызовов) влияет на выгрузку библиотеки?
Вы может и не вызываете, но раз хотите .NET - оно там очень могуче напрягается, чтобы вам его предоставить. Вам наверное будет не сложно пока отключить использование .NET и проверить.
Пока не сложно. Проверил. Без NET выгружается. Другой вопрос: как обеспечить выгрузку с NET, не знаете? Полагаю, спрашивать разрабов квика бесполезно про это...
Способов подключения сборок на си++ как минимум 2: 1. это использовать управляемый код. 2. Использовать интерфейсы и самостоятельно загружать сборки. Тот и другой способ гуглится. Но возможно стоит начать вот CoInitializeEx и CoUninitialize. Но я бы советовал сделать отдельное приложение на .net и передавать туда данные, например по сети.
Не, приложение с передачей данных это такое себе. Это как C# приложение с коннектором C++ - древняя тема и такая же нестабильная. Я пробовал ее году в 2015 еще, че-то не зашло. Я тогда ушел на LUA чистый и его хватало. Сейчас появилась потребность в более нормальном языке, чем LUA и я нашел вариант с подключением библиотеки. Я продолжил бы писать на C# (его знаю, а С++ нет), но проблема в том, что на шарпе нет нормального способа сделать либу. Есть какой-то полукостыльный и он мне не понравился и результат сомнительный. Интерфейсы на чистом Win API тоже не осилил как-то. Вот прикрутил CLR, но оно вон че оказалось. Буду еще смотреть, что дальше делать, но куча посредников между биржей и моим алгоритмом - это печаль и зло. Хочу поменьше, чтоб стабильнее и быстрее было.
Сделай секцию экспорта в C# библиотеке: сначала дезасемблировать, потом прописывать флаги и секции. Я специально программу написал, которая такое делает. И можно использовать LoadLibrary на стороне луа и все другие вкусняшки.
Виталий написал: И что не так? В этой либе мне нужно использовать CLR, там будут формы. Как сам факт поддержки CLR (без каких-либо вызовов) влияет на выгрузку библиотеки?
Как минимум - вот оно коренное отличие вашей DLL от моей, а вовсе не версия QUIK. Ну и видимо передавайте привет .NET и особенностям ее работы.
Цитата
Виталий написал: (без каких-либо вызовов) влияет на выгрузку библиотеки?
Вы может и не вызываете, но раз хотите .NET - оно там очень могуче напрягается, чтобы вам его предоставить. Вам наверное будет не сложно пока отключить использование .NET и проверить.
Пока не сложно. Проверил. Без NET выгружается. Другой вопрос: как обеспечить выгрузку с NET, не знаете? Полагаю, спрашивать разрабов квика бесполезно про это...
Способов подключения сборок на си++ как минимум 2: 1. это использовать управляемый код. 2. Использовать интерфейсы и самостоятельно загружать сборки. Тот и другой способ гуглится. Но возможно стоит начать вот CoInitializeEx и CoUninitialize. Но я бы советовал сделать отдельное приложение на .net и передавать туда данные, например по сети.
Nikolay написал: Не думаю что пойдут на изменение синтаксиса. Я бы больше ожидал стабильности и предсказуемости в вызовах. Сейчас только несколько колбеков типа подключения-отключения-ответ транзакции можно использовать.Остальные не вызывают доверия и надежней баз них. А то когда у тебя колблек от событий прошедших часы назад прилетает после перезапуска терминала, то проще не смотреть на них.
ARQA, имхо, придется, скорее всего, пойти на изменения API по следующе причине: 1) проблеме реализации многопоточности QLua 5.3, которую они не смогли решить до сих пор (с марта 2020 до ноября 2020г.).
Александр М написал: У меня есть двустороннее соглашение со своим брокером, в рамках которого он мне в том числе поставляем Ваше программное обеспечение QUIK, за которое берет арендную плату. Этого достаточно, чтобы тех.поддержка по данному ПО работала.
В таком случае у Вашего брокера и его техподдержки Вы и вправе что-то требовать, если, конечно, это прописано в Вашем договоре с ним. Что касается общения с нами - просим не использовать такие термины. Мы не обязаны делать Вам личный кабинет, давать "в ЛЮБОЙ момент увидеть статус реализации данных пожеланий, его приоритет, а также ориентировочный срок внедрения".
P.S. Вы (справедливости ради не только Вы, но и некоторые другие участники в том числе и данного обсуждения) прямо нарушают правила форума, рекламируя на нашем ресурсе свои сайты. То, что мы пока смотрим на это сквозь пальцы, в том числе и означает уровень нашего хорошего отношения к Вам лично и к другим подобным участникам. Но движение навстречу должно быть обоюдным, надеемся на Ваше понимание.
Подключить Jira или какой-то другой бактрекер было бы хорошим тоном для такого проекта. Запишите это в качестве предложения.
swerg написал: Ладно, хрен с ним с этим троллем. Я на самом деле никак не могу получить ответ на свой вопрос, который давно меня заботит. Ну вот как это сделано в метатрейдере, в других терминалах? нигде ж нет никакого main(). Есть по сути просто скрипт с колбеками (да? я не ошибаюсь?) И вот когда в этих системах прекращается вызов этих колбеков?? я никак не могу этот момент найти, или ищу плохо. Или там после запуска скрипта вызов из него колбеков никогда не прекращается? Расскажите, а
Вообще-то, решение в виде бесконечного цикла , которое обеспечивает работу системы известно давно и широко используется, например в ОС микроконтроллеров (arduino).
Такое решение типично для одноядерных SOC.
Полагаю что проблема КВИКа в том, что VM LUA встраивалась в уже готовую систему, вместо того, чтобы дать пользователям нормальный API к функциям торгового терминала.
Кроме того, как неоднократно подчеркивали сами разработчики, они встраивали луа не для разработки торговых роботов , а для буратин и хрен знает зачем.
Чтобы заменить QPile :) Вопрос к разработчикам: Когда выйдет новая версия?
Добрый день.
Новая версия Lua? Сроков к сожалению назвать не можем. Следите за обновлениями.
Когда будет версия, в которой разработчики изменят работу с коллбэков Lua.
Как уже сообщили сроков назвать не можем. Следите на обновлениями.
Раскройте хотя бы тайну: это будет 2-х потоковая схема или одно потоковая (и придется все скрипты переписывать)?