Владимир написал: Quikos, Нет, это сразу была жопа: какая-то инициализация, выполняемая до мейн, потом эти дурацкие эесепшены... в общем, "говно как говно". :: А классы - это пародия на сишные структуры.
1)Классы это более удобное использование структур. 2)Никто вас не заставляет использовать эксепшины.
В этом и есть удобство С++, что его можно использовать, как хочешь - как чистый Си, как чистый С++(в зависимости от стандарта), любая смесь двух языков. А вот, когда и если в каком то стандарте откажутся от совместимости с Си - вот тогда да... а пока охладите пукан :)
Владимир написал: Quikos, дык со Страуструпа я и начинал. :: А без полной совместимости это говно не продержалось бы и недели. Кстати, я почти всю жизнь пользовался именно компиляторами С++, но только потому, что там есть строчные комментарии.
Ну так с него начали и им и заканчивайте. Или пишите свой язык. :) А если чуть серьезнее - то какое Вам дело, кто и как пишет свой код ?
Владимир написал: В кои-то веки я снова согласен с nikolz - это насчёт "каши из С и С++". Когда-то давно я два года вёл ветку "С vs С++", где мочил "плюсовиков" со всей дури. ::
Тогда мочите Бьерна Страуструповича, который при создании своего языка поставил условие полной совместимости с Си ;) А то ишЬ какой "мочитель" :)
Квик ПАДАЕТ от простейшего кода - тупо ЗАКРЫВАЕТСЯ:
В квике Lua-скрипт:
Код
function main()
Quik_Lua_connector= require("Quik_Lua_connector")
Quik_Lua_connector.run_Cpp()
-------------------------
while not stopped do
sleep(1)
end
-------------------------
end
То есть из Квика запускаю функцию run_Cpp из .dll:
function main()
Quik_Lua_connector= require("Quil_Lua_connector_work_TEST")
Quik_Lua_connector.TestFunc_run_WinConsole_for_dll()
Quik_Lua_connector.run_Cpp()
-------------------------
while not stopped do
sleep(1)
end
-------------------------
end
В С++ соответственно:
Код
static int run_Cpp(lua_State* Lua_stek)
{
lua_State* L = luaL_newstate();
if (L == NULL)
{
std::cout << "L == NULL" << std::endl; //Ошибки нет.
}
lua_getglobal(L, "CreateDataSource");
lua_pushstring(L, "TQBR");
lua_pushstring(L, "GAZP");
lua_pushnumber(L, "INTERVAL_MN1");
std::cout << "Size_stack:" << lua_gettop(L) << std::endl; //Размер 4 - как и должно быть
int status_lua_pcall = lua_pcall(L, 3, 2, 0);
if(status_lua_pcall != 0)
{
std::cout<<"Error"<<std::endl; //attempt to call a nil value
}
}
То есть я хочу использовать автоматически не созданный при вызове функции run_Cpp - Lua стек, а создать своей новый - через luaL_newstate. Стек создается, он не равен нулю. В стек добавляются элементы - то есть он рабочий. Но, как я вызываю lua_pcall - то lua_pcall завершается ошибкой "attempt to call a nil value".
Со автоматически созданный стеком Lua_stek - никаких ошибок нет, все работает.
nikolz написал: Вы можете передать любые параметры в любую функцию через внешние для нее параметры Это могут быть либо глобальные либо локальные параметры блока Например в вашем случае делаем так:
Код
local param1,param2;
-------------------------------------
function my_callback_ (index)
--Теперь тут доступны внешние локальные параметры...my_table_, param1, param2 - помимо стандартного index
end
----------------
local my_table = CreateDataSource (code_class, code_paper_ interval)
parametr_1 = "1"
parametr_2 = "2"
my_table : SetUpdateCallback ( my_callback )
И не надо огород городить. Вы можете таким же образом передать и таблицу и все что хотите.
Не сочтите за наглость, Вы сами по поняли, что написали ?
1)Во первых даже если мы рассматриваем Lua - где тут передача параметров в функцию ? Я что спрашивал про глобальные параметры ? Почему вы вообще применяется к глобальным переменным термин "передать" ?? Это и так ГЛОБАЛЬНАЯ переменная. 2)Во вторых я четко спросил про Си, то есть, как это реализовать на Lua api в Си.
Будем откровенны - Вы написали очень глупую глупость :)
При вызове SetUpdateCallback по умолчанию передать туда доп. параметры нельзя:
Код
function my_callback_(index)
--index - индекс свечи в таблице my_table, НО сама таблица по умолчанию не приходит, что просто дикость.
end
local my_table = CreateDataSource(code_class, code_paper_ interval)
my_table :SetUpdateCallback(my_callback_)
Но, передать доп. параметры в callback - можно с помощью такой контракции, в данном случае я не знаю, что она означает на Lua, просто подсмотрел на данном форуме:
Код
function my_callback_(my_table_, param1, param2, index)
--Теперь тут доступны переданные дополнительные параметры...my_table_, param1, param2 - помимо стандартного index
end
local my_table = CreateDataSource(code_class, code_paper_ interval)
parametr_1 = "1"
parametr_2 = "2"
my_table :SetUpdateCallback(function(idx)my_callback_(my_table,parametr_1, parametr_2, idx) end)
И теперь параметры замечательно переданы в callback SetUpdateCallback.
И вот подскажите пожалуйста, а можно ли подобное провернуть в Си ??
И с одной стороны все нормально, my_callback_ - вызывается, НО с другой стороны - я ожидаю там увидеть таблицу запалённую данными свечей, а приходит строка:
Код
1
2
3
4
5
6
...
итд
Такое ощущение, как будто бы похоже на размер таблицы, но в какой то момент это число доходит до 3007 и после этого так и приходит 3007 с последующими вызовами my_callback_ .
Непосредственно в скрипте Lua в квике такой странности не наблюдается, все работает нормально. Что это может быть ?
Quikos написал: В документации естественно таких данных нет, но может кто знает ? Когда вызывается callback SetUpdateCallback от CreateDataSource - он вызывается всегда только в одном потоке, как в Lua, так и в С++ ? Кстати интересен данный вопрос и касаемо функции OnQuote. Вопрос естественно связан с синхронизацией доступа в случае - многотонной SetUpdateCallback .
Какая разница в каком потоке вызывается функция?
И вот продолжая вышеописанное - если callback вызывается всегда последовательно только в оном потоке - читаю данные из пришедшей таблицы свечей условно в одну static переменную, если же одновременно вызванивается в нескольких потоках, то значит нужно думать дальше и одной переменной не обойтись.
Quikos написал: В документации естественно таких данных нет, но может кто знает ? Когда вызывается callback SetUpdateCallback от CreateDataSource - он вызывается всегда только в одном потоке, как в Lua, так и в С++ ? Кстати интересен данный вопрос и касаемо функции OnQuote. Вопрос естественно связан с синхронизацией доступа в случае - многотонной SetUpdateCallback .
Какая разница в каком потоке вызывается функция? ------------------------- Полагаю Вы знаете, что любая библиотека dll хранится в памяти компа в единственном экземпляре -------------------------------- Это значит, что все потоки, даже если их тысяча вызывают один и тот же код функции ------------------- Важным моментом является какие данные изменяют эти потоки. ------------------ Именно обращение к данным надо синхронизировать, а не обращение к коду функций. ------------------ Уточните свой вопрос.
Предположим я заказал данные свечей к примеру по 10 инструментам и все они будут запрошены на сервере, значит данные придут по мере готовности и callback вызовется по мере готовности.
И вот меня интересует - этот callback - будет вызываться ТОЛЬКО последовательно из одного потока или же функция callback может быть вызвана одновременно сразу из нескольких потоков.
Владимир написал: Quikos, То есть всё, что угодно, кроме самой торговли. :: А зачем Вам тогда Квик и Луа? Лично мне вне торговли ни то, ни другое тыщу лет и даром не надо.
Так я ж и не интересуюсь, что Вам нужно от Квика в торговле и в не её :)
Мне интересно знать callback SetUpdateCallback - однопоточный или может вызываться из разных потоков одновременно.
Владимир написал: Quikos, А что душе угодно? :: Моей душе угодно, чтобы скрипт зарабатывал деньги, и, желательно, вообще без моего участия. И никакой Си для этого нафиг не нужен.
Передача по сети, визуализация, взаимодействие с другими приложениям. Души у всех разные :)
Владимир написал: Quikos, А ЗАЧЕМ? Зачем использовать Си для решения столь примитивной задачи как организация торговли на бирже? Зачем связываться с компиляторами, библиотеками и всем прочим?
Чтобы делать с полученными данными, все что душе угодно.
Владимир написал: Quikos, Я с самого начала говорил, что несмотря на то, что Си мой наилюбимейший язык на протяжении десятилетий, а Lua, пожалуй, наихудший из всех, которые я знаю, писать нужно на чистом Lua, именно с целью обеспечения максимальной надёжности. Именно поэтому (а также потому, что я в своё время вывел всю обработку в поток main) мой скрипт всё ещё работает, и ему почти безразлична как версия языка, так и версия терминала. Не говоря уже про "неудачные сборки библиотек".
Да, но если убрать фактор "неудачные сборки библиотек", то из Си - Вы все равно вызываете Lua код, только сишный. То есть Вы все равно используете Lua библиотеку же, так же работаете со стеком Lua только из Си. Тогда в чем разница ?
Владимир написал: Quikos, Да перестаньте Вы фигнёй страдать, забудьте про С, потоки, dll и вообще любые библиотеки. Пишите на чистом Lua, а там пользуйтесь только sendTransaction, OnTrade и ТТТ - тогда, возможно, Ваш скрипт более-менее нормально ещё проработает некоторое время. И пользуйтесь максимально возможными старыми версиями Квика - по той же причине. Система давно пошла вразнос, её нужно переписывать полностью, с абсолютного нуля.
Спасибо. Но, если Вы пишите, что система пошла в разнос, то какая разница на чем писать скрипт на Си или Lua?
Для моих целей у меня есть скрипт на Lua, но Lua мне не нужен.
Подскажите пожалуйста, есть ли пример, как вызывать функцию к примеру SetUpdateCallback с передачей в нее параметров ?
Ну то есть, вот аналог код в Lua:
Код
local my_table_= CreateDataSource(code_class_, code_paper_, interval)
my_table_:SetUpdateCallback(function(idx)my_callback_(my_table_, code_class_, code_paper_, interval) end)
Код
function my_callback_(my_table_, code_class, code_paper, interval)
...код
end
Код
//В L - на вершине стека уже находится таблица возвращенная CreateDataSource.
lua_getfield(L, -1, "SetUpdateCallback"); //"Извлекаем" на вершину стека из "таблицы" функцию SetUpdateCallback.
Теперь нужно поместить в стек последовательно параметры функции SetUpdateCallback, но тут уже не могу понять: - как поместить function(idx) - как поместить my_callback_
Не могу понять, где должна быть объявлена моя функция callback ?
В Lua скрипте и тогда мне ее нужно просто получить через Lua_global или же в C++ ?
Подскажите, кто нибудь сталкивался с такой проблемой ?
Простейший пример:
Скрипт Lua:
Код
function main()
Quik_Lua_connector = require("Quik_Lua_connector")
Quik_Lua_connector.run_CPP()
-------------------------
while not stopped do
sleep(1)
end
-------------------------
end
С++:
Код
#include "my_func.h"
extern "C"
{
#include "lauxlib.h"
#include "lua.h"
}
#pragma comment(lib,"C:\\Users\\lua54.lib")
int forLua_run_CPP(lua_State* L)
{
int status - my_func(L);
return 0;
}
my_func.h: отдельным файлом:
Код
#pragma once
extern "C"
{
#include "lauxlib.h"
#include "lua.h"
}
int my_func(lua_State* L)
{
int my_int =5;
return my_int ;
}
Соответственно - все компилируется, запускаю скрипт в Квике и квик сообщает об ошибке:
Код
error loading module 'Quik_Lua_connector' from file 'C:\SBERBANK\QUIK_x64_KA\Quik_Lua_connector.dll':
Не найдена указанная процедура.
И вся проблема из за того, что я подключим хедеры Lua в отдельном my_func.h. Если я убираю include из my_func.h. и соответвенно убирают "lua_State* L" из параметров функции, то все работает.
Вызов простой функции Lua из С++ ВСЕГДА приводит к ошибке:
Lua_code:
Код
function my_func_Lua()
message("my_func_Lua")
end
function main()
Quik_Lua_connector = require("Quik_Lua_connector_TEST")
Quik_Lua_connector_TEST()
-------------------------
while not stopped do
sleep(1)
end
-------------------------
end
C++ код:
Код
static int Quik_Lua_connector_TEST(lua_State* L)
{
std::cout << "Start" << std::endl;
lua_getglobal(L, "my_func_Lua"); // получаю функцию
//Проверяю, что на вершине стека находится теперь именно функция: int status_lua_is_function = lua_isfunction(L, -1);
std::cout << "status_lua_is_function:" << status_lua_is_function << std::endl; //return 1 - значит Lua функция.
int status = lua_pcall(L, 0, 0, 0); //Вызываю функцию без аргументов и бещ возвратного значения.
if (status != 0)
{
std::cout << "error:" << lua_tostring(L, -1) << std::endl; //ОШИБКА: error in error handling
}
}
lua_pcall ВСЕГДА завершается ошибкой "error in error handling"
lua_getfield(L, -1, "Size"); //Извлекаю ключ Size из таблицы и помещаю на вершину стека
//Проверяю, что на вершине стека:
int status_lua_isC_function = lua_iscfunction(L, -1);
std::cout << "status_lua_isC_function:" << status_lua_isC_function << std::endl; //return 1
int status_lua_is_function = lua_isfunction(L, -1);
std::cout << "status_lua_is_function:" << status_lua_is_function << std::endl; //return 1
//return 1 - означает на вершине стека - функция - видимо извлеченная функция Size.
lua_pushvalue(L, -2); // Создаю копию таблицы и помещаю ее на вершину стека после функции Size.
int status_lua_pcall = lua_pcall(L, 1, 1, 0); // Вызываю функцию Size с аргументом в виде таблицы и одним возвращаемым значением
if (status_lua_pcall == LUA_ERRERR)
{
std::cout << "LUA_ERRERR" << std::endl;
}
lua_pcall - всегда завершается ошибкой LUA_ERRERR - ошибка во время выполнения обработчика ошибок.
int size_stack = lua_gettop(L);
std::cout << size_stack << std::endl; //Размер стека 1
lua_pushstring(L, "Size");
size_stack = lua_gettop(L);
std::cout << size_stack << std::endl; //Размер стека 2
lua_gettable(L, -2); //lua_gettable - помешает на вершину стека значение Таблицы, которая расположена первый элементом в стеке по ключу расположенному на вершине стека, то есть по ключу "Size"
size_stack = lua_gettop(L);
std::cout << size_stack << std::endl; //Размер стека 2, то есть lua_gettable - доабвила значение по ключу Size за место доавленной выше строки "Size"
std::cout << "Size_number:" << lua_tonumber(L, -1) << std::endl; //Извлекаю значение с вершин стека, НО оно равно НУЛЮ!!! ХОТЯ таблица переданная из Lua в Си - гарантировано имеет размер
local my_table_ = CreateDataSource(code_class_, code_paper_, interval)
local size_table = my_table_:Size() //Гарантировано не равно нулю.
Отправляю в dll в Си:
Код
Quik_Lua_connector.get_data_frim_Lua(size_table)
В dll принимаю:
Код
static int forLua_get_data_frim_Lua(lua_State* L)
{
std::cout << "Size:" << lua_tonumber(L, -1) << std::endl; //Снимаю данные с вершины стека. Все выводится на косноль нормально.
}
Теперь я хочк передать не отдельный параметр полученной таблицы my_table_, а сразу всю таблицу:
Отправляю в dll в Си:
Код
Quik_Lua_connector.get_data_frim_Lua(size_table)
В dll принимаю:
Код
static int forLua_get_data_frim_Lua(lua_State* L)
{
lua_pushnumber(L, 1); //Добавляю в стек номер индекса переданной таблицы к элементу которой я хочу получить доступ. lua_gettable(L, 1); //Помещает на вершину стека переданной таблицы - расположенная по 1 элементу в стеке, и индексу в самой таблице - по номеру элемента с вершины стека, то есть с номера "1", которая я добавил строчкой выше.
lua_getfield(L, -1, "Size"); //Теперь беру значение из стека с вершины стека, то есть то значние, которое я извлек из таблицы по индексу "1" (грубо говоря первая свеча) и извлекаю из него поле с заданным именем "Size" и значение этого поля помещается на вершину стека.
std::cout << "Size:" << lua_tonumber(L, -1) << std::endl; //Беру значение с вершины стека и получаю дулю с маслом или ошибку "unrecognized exception" в самом квике.
}
То есть передать обычную таблицу в виде массива из Lua в Си и получить доступ к значнеием - не составляет проблемы, а передача таблицы с ключом и плучение доступа по ключу не работает в Квике.