<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[QUIK -> DDE &mdash; Написание внешних библиотек на C++/Delphi/C# для Lua]]></title>
		<link>https://quik2dde.ru/index.php</link>
		<atom:link href="https://quik2dde.ru/extern.php?action=feed&amp;fid=14&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние темы раздела «QUIK -> DDE».]]></description>
		<lastBuildDate>Sat, 02 Nov 2024 09:00:12 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Обмен данными между стеками разных LuaState.]]></title>
			<link>https://quik2dde.ru/viewtopic.php?id=454&amp;action=new</link>
			<description><![CDATA[<p>Никак не могу понять, почем не присвоить ключ и значение, переданных из другого стека, таблице в стеке другого состояния.<br />В L2 находится всё, что надо, но код не идёт. </p><div class="codebox"><pre><code>#include &lt;windows.h&gt;
#include &lt;string&gt;

#include &lt;lua.hpp&gt;


BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
    return TRUE;
}

std::string CheckStack(lua_State* L, std::string message = &quot;&quot;) {
    std::string str = &quot;&quot;;
    int top = lua_gettop(L);

    for (int i = -1; i &gt;= 0 - top; i--) {
        std::string type_name = luaL_typename(L, i);
        std::string s = &quot;&quot;, ls = &quot;&quot;, t = &quot;&quot;;

        switch (lua_type(L, i)) {
        case LUA_TNONE: t = &quot;LUA_TNONE&quot;; break;
        case LUA_TNIL: t = &quot;LUA_TNIL &quot;; break;
        case LUA_TBOOLEAN:
            s = lua_toboolean(L, i) ? &quot;true&quot; : &quot;false&quot;;
            t = &quot;LUA_TBOOLEAN &quot;;
            break;
        case LUA_TLIGHTUSERDATA: t = &quot;LUA_TLIGHTUSERDATA &quot;; break;
        case LUA_TNUMBER:
            s = std::to_string(lua_tonumber(L, i));
            t = &quot;LUA_TNUMBER &quot;;
            break;
        case LUA_TSTRING:
            ls = lua_tostring(L, i);
            s = &quot;\&quot;&quot; + ls + &quot;\&quot;&quot;;
            t = &quot;LUA_TSTRING &quot;;
            break;
        case LUA_TTABLE: t = &quot;LUA_TTABLE &quot;; break;
        case LUA_TFUNCTION: t = &quot;LUA_TFUNCTION &quot;; break;
        case LUA_TUSERDATA: t = &quot;LUA_TUSERDATA &quot;; break;
        case LUA_TTHREAD: t = &quot;LUA_TTHREAD &quot;; break;
        }

        str += &quot;|&quot; + std::to_string(i) + &quot;; &quot; + std::to_string(top + i + 1) + &quot;| &quot;
            + t + type_name + &quot; &quot; + s + &quot;\n&quot;;
    }

#ifdef UNICODE
    MessageBoxW(NULL, str.c_str(), message.c_str(), MB_OK);
#else
    MessageBoxA(NULL, str.c_str(), message.c_str(), MB_OK);
#endif
    return str;
}

void F() {
    lua_State* L1 = luaL_newstate();
    lua_State* L2 = luaL_newstate();
    lua_newtable(L1);
    lua_newtable(L2);
    // заполняем таблицу:
    lua_pushstring(L1, &quot;QW&quot;);
        CheckStack(L1, &quot;1 L1&quot;);
    lua_pushnumber(L1, 11);
        CheckStack(L1, &quot;2 L1&quot;);
    lua_settable(L1, -3);
        CheckStack(L1, &quot;3 L1&quot;);
    // возвращаем из таблицы значение:
    lua_pushstring(L1, &quot;QW&quot;);
        CheckStack(L1, &quot;4 L1&quot;);
    lua_gettable(L1, -2);
        CheckStack(L1, &quot;5 L1&quot;);
    // вводим ключ:
    lua_pushstring(L1, &quot;QW&quot;);
        CheckStack(L1, &quot;6 L1&quot;);
    // меняем ключ изначение местами:
    lua_insert(L1, -2);
        CheckStack(L1, &quot;7 L1&quot;);
    // переносим ключ и значение из L1 в L2:
    lua_xmove(L1, L2, 2);
        CheckStack(L1, &quot;8 L1&quot;);
        // на стеке L2 ключ и значение в нужном порядке!
        CheckStack(L2, &quot;1 L2&quot;);
    // вводим ключ и значение в таблицу в L2:
    lua_settable(L2, -3);
        CheckStack(L2, &quot;2 L2&quot;);
    // вводим ключ:
    lua_pushstring(L2, &quot;QW&quot;);
        CheckStack(L2, &quot;3 L2&quot;);
    // возвращаем значение:
    lua_gettable(L2, -2);
    // и - ничего не получили!
        CheckStack(L2, &quot;4 L2&quot;);

    lua_close(L1);
    lua_close(L2);
    //==================================================
     
    // А этод код работает!
    lua_State* L3 = luaL_newstate();
    lua_State* L4 = luaL_newstate();
    lua_newtable(L3);
    lua_newtable(L4);
    // заполняем таблицу:
    lua_pushstring(L3, &quot;QW&quot;);
    lua_pushnumber(L3, 11);
    lua_settable(L3, -3);
    // возвращаем из таблицы значение:
    lua_pushstring(L3, &quot;QW&quot;); 
        CheckStack(L3, &quot;1 L3&quot;);
    // возвращаем из таблицы значение:
    lua_gettable(L3, -2);
        CheckStack(L3, &quot;2 L3&quot;);

    // вводим ключ в L4:
    lua_pushstring(L4, &quot;QW&quot;);
        CheckStack(L4, &quot;1 L4&quot;);
    // переносим значение из L3 в L4:
    lua_xmove(L3, L4, 1);
        CheckStack(L4, &quot;2 L4&quot;);
    // заполняем таблицу:
    lua_settable(L4, -3);
        CheckStack(L4, &quot;3 L4&quot;);
    // вводим ключ:
    lua_pushstring(L4, &quot;QW&quot;);
        CheckStack(L4, &quot;4 L4&quot;);
    // возвращаем значение:
    lua_gettable(L4, -2);
    // всё в порядке!
        CheckStack(L4, &quot;5 L4&quot;);

    lua_close(L3);
    lua_close(L4);
}

int Start(lua_State* L) { F(); return 0; }

static struct luaL_Reg ls_lib[] = {{ &quot;Start&quot;, Start },{NULL, NULL}};

extern &quot;C&quot; __declspec(dllexport) int luaopen_LuaSt(lua_State* L) {
    luaL_newlib(L, ls_lib);
    return 1;
}</code></pre></div><p>Прошу помощи!<br />Если можно объяснить подробно (для &quot;особо одарённых&quot;). <br />Заранее благодарю!</p>]]></description>
			<author><![CDATA[null@example.com (Yuriy)]]></author>
			<pubDate>Sat, 02 Nov 2024 09:00:12 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?id=454&amp;action=new</guid>
		</item>
		<item>
			<title><![CDATA[SetUpdateCallback и обнуление стека Lua]]></title>
			<link>https://quik2dde.ru/viewtopic.php?id=446&amp;action=new</link>
			<description><![CDATA[<p>Здравствуйте,</p><p>Раньше все работало, сейчас, как будто бы перестало.</p><p>Естественно использую LUA C API - для вызова SetUpdateCallback, вот такой просто С++ код:&nbsp; да понимаю, что вероятность, что кто-то будет смтреть код стремится к нулю, поэтому срезюмирую поведение кода:</p><p>С помощью QLua C API:</p><p>-1:Я вызываю CreteDataSorce: вызов происходит успешно, мне возвращается таблица и нулевая ошибка.<br />-2:Я подтверждаю это проверкой стека Lua: на вершине стека находится таблица и нулевая ошибка.</p><br /><p>-3:Затем я вызываю SetUpdateCallback и передаю вв него саму колбек функцию, которая будет вызыватся при каждой совершенной сделке.&nbsp; Так же дополнительно я связываю по типу лямбды любое значение, чтбы предать для последующего ивзлечения его в самом колбеке.</p><p>-4:Вызыва SetUpdateCallback, убеждаюсь, что вызов SetUpdateCallback прошел успешно и опять проверяю стек на наличие ранее заказанной таблицы CreateDataSource - ОНИ НА МЕСТЕ!<br />.<br />-5: И наконец на рынке совершается сделка по заказанному инстурменту и вызывается колбек &quot;my_callback__for__SetUpdateCallback&quot;. Все что я делаю в данном примере в этом колбеке это проверяю наличие моей таблицы CrateDataSourc в стеке Lua. ИИИИИИ ее там нет!!!! Весь стека кромер первого элемента был &quot;кем-то&quot; очищен!</p><p>ВОПРОС: КТО И ЗАЧЕМ очитстил стек ?? КАК видно из кода, между вызовов SetUpdateCallback и вызовом самой колбек-функции нет ни одной строчки кода, которая бы редактировала стек. Так что происходит тогда ?</p><br /><br /><br /><div class="codebox"><pre><code>lua_State* L_global;
int static nummer_table_from_stack;</code></pre></div><br /><br /><br /><div class="codebox"><pre><code>void SetUpdateCallcak_wrapper(lua_State* L)
{

    L_global = L;
    std::cout &lt;&lt; &quot;L_global_adress:&quot; &lt;&lt; &amp;L_global &lt;&lt; std::endl;


    //-----------------------------------------------------------------1-Вызовем функцию CreateDataSource:Начало--------------------------------------------
    lua_getglobal(L, &quot;CreateDataSource&quot;);                 

    lua_pushstring(L, &quot;TQBR&quot;);       //Добавим первый параметр функции CreateDataSource на вершину стека
    lua_pushstring(L, &quot;SBER&quot;);          //Добавим второй параметр функции CreateDataSource на вершину стека
    lua_pushnumber(L, 1);            //Добавим третий параметр функции CreateDataSource на вершину стека

    int status_lua_pcall = lua_pcall(L, 3, 2, 0);    //Так как все необходимые параметры добавлены в стек, то вызываем функцию lua_pcall - которая использя доабвенные параметры в правильном порядке - реализует вызов функции CreateDataSource: 2-ой параметр - это число аргументов, которые мы добаили в стек и которая принимает функция CreateDataSource; 2-ой: параметр - это число параметров, которое возвращает функция CreateDataSource. После успешного выполнения lua_pcall удаляет и значение функции и переданные аргменты со стека в кол-во указанном во втором параметре(не велючая функцию) и доабвляеи результат на стек в кол-во указанном во втором параметре.
    //-----------------------------------------------------------------1-Вызовем функцию CreateDataSource:Конец--------------------------------------------



    //-------------------------------------------------------------------5-Проверка на ошибку lua_pcall:Начало---------------------------------------------------------------------
    if (status_lua_pcall != 0)
    {
        //Ошибка произошла при вызове функции lua_pcall при вызове CreateDataSource:
        std::cout &lt;&lt; &quot;ERROR CreateDataSource&quot; &lt;&lt; std::endl;
        return;
    }
    //-------------------------------------------------------------------5-Проверка на ошибку lua_pcall:Конец---------------------------------------------------------------------
    else
    {

         nummer_table_from_stack = lua_gettop(L) - 1;   //Это номер элемента в стеке L - в котором теперь размещается полученная от CreateDataSource таблица. &quot;-1&quot; - потому что CreateDataSource поместила на вершину стека две перменные: таблицу и переменную об ошибке. То есть таблица находить на предпоследнем месте с вершины стека.

         my_call_SetUpdateCallback(L);     //Вызываем SetUpdateCallback wrapper
    }

}</code></pre></div><br /><br /><div class="codebox"><pre><code>l
static void ckeck_Lua_Stack(lua_State* L)
{

    std::cout &lt;&lt; &quot;----------------------------------------&quot; &lt;&lt; std::endl;

    int top = lua_gettop(L);
    std::cout &lt;&lt; &quot;Total element is stack:&quot;&lt;&lt; top &lt;&lt; std::endl;

    for (int i = 1; i &lt;= top; i++) 
    {
        int type = lua_type(L, i);

        const char* type_name = lua_typename(L, type);

        std::cout &lt;&lt; &quot;type:&quot; &lt;&lt; type_name &lt;&lt; &quot;:&quot;;


        if (type == LUA_TSTRING || type == LUA_TNUMBER) 
        {
            std::cout &lt;&lt; lua_tostring(L, i) &lt;&lt; std::endl;
        }
        else
        {
            std::cout &lt;&lt; std::endl;
        }
    }
    std::cout &lt;&lt; &quot;----------------------------------------&quot; &lt;&lt; std::endl &lt;&lt; std::endl;


    //std::this_thread::sleep_for(std::chrono::milliseconds(100000));

}</code></pre></div><br /><br /><div class="codebox"><pre><code>static int my_callback__for__SetUpdateCallback(lua_State* L)
{

//Значит произошла сделка!

    std::cout &lt;&lt; &quot;Number_candle:&quot;&lt;&lt; lua_tonumber(L, -1) &lt;&lt; std::endl;

    ckeck_Lua_Stack(L_global);         //Проверяем стек Lua!!! И теперь в нем находится сдедующее:

----------------------------------------
Total element is stack:1                          //Куда черт возьми делать моя ранее заказанная таблица CreateDataSource ?????
type:number:1
----------------------------------------


    return 0;

}</code></pre></div><br /><br /><br /><div class="codebox"><pre><code>static void my_call_SetUpdateCallback(lua_State* L)
{

    
    //--------------------------------------------------------
    lua_getfield(L_global, nummer_table_from_stack, &quot;SetUpdateCallback&quot;);                       //&quot;Извлекаем&quot; из &quot;таблицы&quot; функцию SetUpdateCallback.
     
    lua_pushvalue(L_global, nummer_table_from_stack);                                                       //Помещаем копию обьекта таблицы CreateDataSource на вершину стека.
    //--------------------------------------------------------


    lua_pushnumber(L_global, 555);  //Просто для примера связываю какое то любое значение для передачи в колбек. 

    lua_pushcclosure(L_global, my_callback__for__SetUpdateCallback, 1);       //Захватываем.


    //--------------------------------------------------------
    int status_lua_pcall = lua_pcall(L_global, 2, 0, 0);                  //Реализауем вызов функции SetUpdateCallback с аргументом таблицы, которую поместили на вершину стека 
    //--------------------------------------------------------
    

    if (status_lua_pcall != 0)
    {
        std::cout &lt;&lt; &quot;lua_pcall__ERROR&quot; &lt;&lt; std::endl;
        return; 
    }
    else
    {
        std::cout &lt;&lt; &quot;SetUpdateCallback Success Call&quot; &lt;&lt; std::endl;
        
        ckeck_Lua_Stack(L_global);       //Проверяю что находится на данный момент в стеке Lua.

       //Находится следующее:

 ----------------------------------------
Total element is stack:3
type:string:1     //Таблица глобьальный функций
type:table:        //Это как раз запрошенная таблица CreateDataSource
type:nil:            //Ошибка при запросе таблицы CreateDataSource - то есть nil - ошибки нет.
----------------------------------------

        return;
    }


}</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (Serg_)]]></author>
			<pubDate>Thu, 07 Dec 2023 08:04:48 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?id=446&amp;action=new</guid>
		</item>
		<item>
			<title><![CDATA[Обращение к функциям QLUA из новой VMLua в новом потоке]]></title>
			<link>https://quik2dde.ru/viewtopic.php?id=432&amp;action=new</link>
			<description><![CDATA[<p>Добрый день,swerg<br />Буду признателен, если подскажите как реализовать обращение к&nbsp; функциям библиотеки QLUA&nbsp; <br />из новой VMLua в новом потоке.<br />Поток и новый стейт запускаем на СИ. <br />-----------------<br />Спасибо.</p>]]></description>
			<author><![CDATA[null@example.com (nikolz)]]></author>
			<pubDate>Sat, 04 Mar 2023 11:30:20 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?id=432&amp;action=new</guid>
		</item>
		<item>
			<title><![CDATA[OnAllTrade на Lua C API]]></title>
			<link>https://quik2dde.ru/viewtopic.php?id=424&amp;action=new</link>
			<description><![CDATA[<p>Подскажите пожалуйста, а как вызвать функцию OnAllTrade на Lua C ?</p><p>Что то я в ступор встал - одно дело к примеру вызывать CreateDataSource для которого нужно указывать callback функцию и создать callback-функцию на Си.</p><p>А тут нет callback функции, собственно сама OnAllTrade - является одной глобальной callback-функцией.</p><br /><p>Ну то есть я могу поместить на стек эту функцию:</p><div class="codebox"><pre><code>lua_getglobal(L, &quot;OnAllTrade &quot;);</code></pre></div><p>И вызвать lua_pcall...&nbsp; ну дальше то что ? Это же не &quot;обычная&quot; функция.</p><p>Но, на этом мое понимание заканчивается. <img src="https://quik2dde.ru/img/smilies/sad.png" width="15" height="15" alt="sad" /></p>]]></description>
			<author><![CDATA[null@example.com (Serg_)]]></author>
			<pubDate>Thu, 17 Nov 2022 20:07:53 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?id=424&amp;action=new</guid>
		</item>
		<item>
			<title><![CDATA[Как собрать Lua либу под WIndows]]></title>
			<link>https://quik2dde.ru/viewtopic.php?id=423&amp;action=new</link>
			<description><![CDATA[<p>Подскажите пожалуйста, как все таки собрать библиотеку Lua под WIndows ?</p><p>Ну вот есть у меня исходные .с и .hpp файлы. Есть Make файл.<br />А что с ними в итоге дальше то нужно делать ? В Cmake`е&nbsp; &nbsp;makefile не открывается.</p>]]></description>
			<author><![CDATA[null@example.com (Serg_)]]></author>
			<pubDate>Tue, 15 Nov 2022 20:04:09 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?id=423&amp;action=new</guid>
		</item>
		<item>
			<title><![CDATA[Как вызвать у таблицы - "строковую переменную" ?]]></title>
			<link>https://quik2dde.ru/viewtopic.php?id=421&amp;action=new</link>
			<description><![CDATA[<p>Чтобы вызвать метод у таблицы, к примеру метод Size() у таблицы CreateDataSource - нужно сделать так:</p><div class="codebox"><pre><code>       //index - номер таблицы в стеке Lua

    lua_getfield(L, index, &quot;Size&quot;);            //&quot;Извлекаем&quot; из &quot;таблицы&quot; функцию отвечающую за возвращения размера этой таблицы.
    lua_pushvalue(L, index);                //Помещаем копию обьекта таблицы на вершину стека.

    int status_lua_pcall = lua_pcall(L, 1, 1, 0);      //Вызываем функцию Size </code></pre></div><br /><p>А как сделать тоже самое, но не с методом таблицы, а со строковым полем ? К примеру, как в getQuoteLevel2: [url]https://luaq.ru/getQuoteLevel2.html[/url]</p><p>У таблицы есть поле bid_count/bid_count, но такой же код не прокатывает:</p><div class="codebox"><pre><code>    lua_getfield(L, index, &quot;bid_count&quot;);            //&quot;Извлекаем&quot; из &quot;таблицы&quot; функцию отвечающую за возвращения размера этой таблицы.
    lua_pushvalue(L, index);                //Помещаем копию обьекта таблицы на вершину стека.

    int status_lua_pcall = lua_pcall(L, 1, 1, 0);      //Вызываем функцию Size </code></pre></div><br /><p>Ошибка: attempt to call a string value</p>]]></description>
			<author><![CDATA[null@example.com (Serg_)]]></author>
			<pubDate>Thu, 03 Nov 2022 20:07:55 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?id=421&amp;action=new</guid>
		</item>
		<item>
			<title><![CDATA[Отписка от колбека SetUpdateCallback и сразу же подписка]]></title>
			<link>https://quik2dde.ru/viewtopic.php?id=418&amp;action=new</link>
			<description><![CDATA[<p>Что то фигня получается, я подписываюсь на акцию к примеру Сбера - все окей - обновляемые данные приходят.<br />Через некоторые время я отписываюсь от колбека и через несколько секунд опять подписываюсь, подписка проходит без ошибок, НО - колбек уже не вызывается, то есть обновляемые данные не хотят уже приходить.</p><p>Вот код демонстрирующий это:</p><br /><br /><div class="codebox"><pre><code>global_cntr=0;



function my_callback_CreateDataSource_(my_table_data_candle_, code_class_, code_paper_, interval_, idx)


message(code_paper_ ..&quot;:&quot; .. interval_string_..&quot;:&quot; ..tostring(my_table_data_history_candle_:C(idx))  )




if global_cntr == 13 then

my_table_data_history_candle_:Close()     --отписываемся
message(&quot;CLOSE&quot;)

end
global_cntr=global_cntr+1


end








function main()

message(&quot;start&quot;)

local code_class_1= &quot;TQBR&quot;          
local code_paper_1= &quot;SBER&quot;
local intervakla_1= INTERVAL_M1



local my_table_1, error_desc_1 = CreateDataSource(code_class_1, code_paper_1, intervakla_1)  


------------------------Проверка на ошибки:-------------------
if error_desc_1 ~= nil then 
message(&quot;1:&quot; .. error_desc_1)
end
--------------------------------------------------------------

status = my_table_1:SetUpdateCallback(function(idx)my_callback_CreateDataSource_(my_table_1, code_class_1, code_paper_1, intervakla_1, idx) end)









while not stopped do 

sleep(1)

if global_cntr == 14 then

message(&quot;START_2&quot;)

local code_class_1= &quot;TQBR&quot;          
local code_paper_1= &quot;SBER&quot;
local intervakla_1= INTERVAL_M1



local my_table_2, error_desc_2 = CreateDataSource(code_class_1, code_paper_1, intervakla_1)  


------------------------Проверка на ошибки:-------------------
if error_desc_2 ~= nil then 
message(&quot;1:&quot; .. error_desc_2)
end
--------------------------------------------------------------

status = my_table_2:SetUpdateCallback(function(idx)my_callback_CreateDataSource_(my_table_2, code_class_1, code_paper_1, intervakla_1, idx) end)

message(tostring(status))

global_cntr = global_cntr + 1

message(&quot;END&quot;)
break

end


end








-------------------------
while not stopped do 
sleep(1)
end 
-------------------------



end -- end main()</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (Serg_)]]></author>
			<pubDate>Thu, 03 Nov 2022 07:37:50 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?id=418&amp;action=new</guid>
		</item>
		<item>
			<title><![CDATA[Ошибка ACCESS VIOLATION при подключении внешней dll в lua]]></title>
			<link>https://quik2dde.ru/viewtopic.php?id=417&amp;action=new</link>
			<description><![CDATA[<p>Приветствую форумчане.</p><p>Имеется сторонняя dll написанная на c++ для получения из quik9.5 свечек по команде, собрана под lua5.3, а также имеется lua скрипт, который должен эти самые свечки отправлять в dll, а затем в приложение написанное на c#.</p><p>Для сборки dll используется VS 2019 в release x64.</p><p>Dll помещается в корень quik`а.</p><p>Суть проблемы - при запуске в quik lua-скрипта, терминал выплёвывает ошибку ACCESS VIOLATION at address SOME_ADDRESS.</p><p>Код dll<br /></p><div class="codebox"><pre><code>#include &lt;windows.h&gt;
#include &lt;process.h&gt;

// необходимые для Lua константы
#define LUA_LIB
#define LUA_BUILD_AS_DLL

// заголовочные файлы LUA
extern &quot;C&quot; {
#include &quot;Lua\lauxlib.h&quot;
#include &quot;Lua\lua.h&quot;
}

TCHAR CommandMemory[] = TEXT(&quot;Memory4CommandGetCandles&quot;);
TCHAR CandlesMemory[] = TEXT(&quot;Memory4GetCandles&quot;);

HANDLE CommandFileMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 64, CommandMemory);
HANDLE CandlesFileMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 128, CandlesMemory);

// точка входа DLL
BOOL APIENTRY DllMain(HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    return TRUE;
}

// функция отправки команд из программы в Lua скрипт
static int forLua_GetCommand(lua_State* L)
{
    if (CommandFileMap) // если память существует
    {
        // считываем данные из памяти и переводим в набор байтов
        PBYTE pb = (PBYTE)(MapViewOfFile(CommandFileMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 64));
        if (pb != NULL) // если есть данные
        {
            if (pb[0] == 0) // если первый байт нулевой
            {
                lua_pushstring(L, &quot;&quot;); // отправляем пустую строку в Lua скрипт
            }
            else
            {
                lua_pushstring(L, (char*)(pb));//иначе отправляем набор байтов в Lua скрипт
            }


            UnmapViewOfFile(pb); // закрываем доступ к данным
        }
        else
        {
            lua_pushstring(L, &quot;&quot;); // иначе отправляем пустую строку в Lua скрипт
        }
    }
    else
    {
        lua_pushstring(L, &quot;&quot;); // иначе отправляем пустую строку в Lua скрипт
    }

    return(1);
}

// функция очистки памяти для отправки команд
static int forLua_ClearCommand(lua_State* L)
{
    if (CommandFileMap)//если память существует
    {
        // считываем данные из памяти и переводим в набор байтов
        PBYTE pb = (PBYTE)(MapViewOfFile(CommandFileMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 64));

        if (pb != NULL) // если есть данные
        {
            // заполняем нулевыми байтами
            for (int i = 0; i &lt; 64; i++)
            {
                pb[i] = &#039;\0&#039;;
            }

            UnmapViewOfFile(pb); // закрываем доступ
        }
    }

    return(0);
}

// функция отправки свечек из lua в программу
static int forLua_SendCandle(lua_State* L)
{
    if (CandlesFileMap) // если память существует
    {
        // считываем данные из памяти и переводим в набор байтов
        PBYTE pb = (PBYTE)(MapViewOfFile(CandlesFileMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 128));
        if (pb != NULL) // если есть данные
        {
            const char* Candle = lua_tostring(L, 1); // переменная для хранения данных
            int Size = 0;

            for (int i = 0; i &lt; 128; i++)
            {
                if (Candle[i] == 0)
                {
                    break;
                }
                else
                {
                    Size++;
                }
            }

            memcpy(pb + 1, Candle, Size); // копируем 
            memcpy(pb, &quot;1&quot;, 1);
            UnmapViewOfFile(pb); // закрываем доступ
        }
    }

    return(0);
}

// регистрация реализованных в dll функций, чтобы они стали &quot;видимы&quot; для Lua
static const struct luaL_Reg ls_lib[] = {
    { &quot;GetCommand&quot;, forLua_GetCommand },
    { &quot;ClearCommand&quot;, forLua_ClearCommand },
    { &quot;SendCandle&quot;, forLua_SendCandle },
    { NULL, NULL }
};

// регистрация названия библиотеки, видимого в скрипте Lua
extern &quot;C&quot; LUALIB_API int luaopen_GetCandlesDll(lua_State * L) {
    lua_newtable(L);
    luaL_setfuncs(L, ls_lib, 0);
    lua_setglobal(L, &quot;GetCandlesDll&quot;);
    return 1;
}</code></pre></div><p>Код lua-скрипта<br /></p><div class="codebox"><pre><code>require(&quot;GetCandlesDll&quot;);

local Candle = &quot;&quot;;
local LastQty = 1;
local CurrentQty = 1;
local DataSet;
local IsOnline = false;
local IsRun = true;

local Minute = &quot;&quot;;
local Hour = &quot;&quot;;

local Day = &quot;&quot;;
local Month = &quot;&quot;;
local Year = &quot;&quot;;

local High = &quot;&quot;;
local Low = &quot;&quot;;
local Open = &quot;&quot;;
local Close = &quot;&quot;;

local ClassName = &quot;TQBR&quot;;
local ToolName = &quot;YNDX&quot;;

function OnInit()
    DataSet = CreateDataSource(ClassName, ToolName, INTERVAL_M1);
end;

function OnStop()
    IsRun = false;
end;

function main()
    while IsRun do
        if tostring(GetCandlesDll.GetCommand()) == &quot;run&quot; then
            IsOnline = true;
            DataSet = CreateDataSource(ClassName, ToolName, INTERVAL_M1);
            GetCandlesDll.ClearCommand();
        end;
        
        if tostring(GetCandlesDll.GetCommand()) == &quot;stop&quot; then
            StopScript();
        end;

        if IsOnline == true then
            CurrentQty = DataSet:Size() - 1;

            if CurrentQty ~= nil and CurrentQty &gt; LastQty then
                for i = LastQty, CurrentQty do
                    if (i == CurrentQty) then
                        LastQty = CurrentQty;
                    end;

                    if tostring(GetCandlesDll.GetCommand()) == &quot;stop&quot; then
                        StopScript();

                        break;
                    end;

                    Minute = tonumber(DataSet:T(i).min) &lt; 10 and &quot;0&quot;..tostring(DataSet:T(i).min) : tostring(DataSet:T(i).min);
                    Hour = tonumber(DataSet:T(i).hour) &lt; 10 and &quot;0&quot;..tostring(DataSetDataSetT(i).hour) : tostring(DataSet:T(i).hour);

                    Day = tonumber(DataSet:T(i).day) &lt; 10 and &quot;0&quot;..tostring(DataSet:T(i).day) : tostring(DataSet:T(i).day);
                    Month = tonumber(DataSet:T(i).month) &lt; 10 and &quot;0&quot;..tostring(DataSet:T(i).month) : tostring(DataSet:T(i).month);
                    Year = tostring(DataSet:T(i).year);
                    
                    High = tostring(DataSet:H(i));
                    Low = tostring(DataSet:L(i));
                    Open = tostring(DataSet:O(i));
                    Close = tostring(DataSet:C(i));
                    
                    Candle = Day..&quot;.&quot;..Month..&quot;.&quot;..Year..&quot; &quot;..Hour..&quot;:&quot;..Minute..&quot;:&quot;..&quot;00&quot;..&quot;;&quot;..High..&quot;;&quot;..Low..&quot;;&quot;..Open..&quot;;&quot;..Close..&quot;;&quot;;

                    sleep(1);
                end;
            end;
        end;

        sleep(1000);
    end;
end;

function StopScript()
    GetCandlesDll.ClearCommand()
    IsOnline = false;
    LastQty = 1;
    Candle = &quot;&quot;;

    if DataSet:Size() ~= nil then 
        DataSet:Close(); 
    end;
end;</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (infinitywaytrader)]]></author>
			<pubDate>Tue, 18 Oct 2022 10:30:26 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?id=417&amp;action=new</guid>
		</item>
		<item>
			<title><![CDATA[SetUpdateCallbackcallback в Lua C api - перезаписывает заказы.]]></title>
			<link>https://quik2dde.ru/viewtopic.php?id=416&amp;action=new</link>
			<description><![CDATA[<p>SetUpdateCallbackcallback в Lua C api - перезаписывает заказы:</p><p>Из скрипта квика вызывается Сищная-функция: в нее соответственно автоматически передается или создается Lua-Стек:&nbsp; </p><br /><p>Код</p><div class="codebox"><pre><code>int my_callback(lua_State* L)
{
//Доп.пераметры извелкаем через lua_upvalueindex.

std::cout&lt;&lt;&quot;interval_int:&quot; &lt;&lt;interval_int &lt;&lt;std::endl;
}



void my_call_CreateDataSource(lua_State* L_, name_class_insrument, name_code_paper, interval_int)
{
lua_getglobal(L, &quot;CreateDataSource&quot;);          

lua_pushstring(L,_ name_class_insrument);    
lua_pushstring(L_, name_code_paper);        
lua_pushnumber(L_, interval_int);                

int status_lua_pcall = lua_pcall(L, 3, 2, 0); 



my_call_SetUpdateCallback(L_, my_callback, name_class_insrument, name_code_paper, interval_int);    //Вызываем SetUpdateCallback и передаем в нее функцкиб обратного вызова и доп.параметры.
}


int ruc_cpp(lua_State* L_main)
{



lua_State* L_1 = lua_newthread(L_main);       //Создаю &quot;поток&quot; связанный с главным стеком.
lua_State* L_2 = lua_newthread(L_main);


my_call_CreateDataSource(L_1 , &quot;TQBR&quot;, &quot;GAZP&quot;, &quot;INTERVAL_H2&quot;);
my_call_CreateDataSource(L_2 , &quot;TQBR&quot;, &quot;GAZP&quot;, &quot;INTERVAL_H4&quot;);






    //-----------------------------------------------
    for (int i = 0; i &lt; 1000000; i++)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(100)); 
    }
    //-----------------------------------------------
}</code></pre></div><br /><p>Приведенный код частично условный, чтобы не загромождать кодом страницу.</p><p>Но суть в том, что - я создаю два новых &quot;потока&quot; от главного Луа-стека:<br />-Вызываю для каждого из двух созданных &quot;потоков&quot; - функцию CreateDataSource и навешиваю колбек через SetUpdateCallback.<br />-Первый и примерно второй и третий - колбеки - выводят интервал &quot;INTERVAL_H2&quot; - то есть это тот интервал, который я запросил первым у CreateDataSource...<br />-НО! Как только вызывается второй CreateDataSource для второго &quot;потока&quot; и навешивается callback - после этого любой вызываемый callback приходит только с интервалом &quot;INTERVAL_H4&quot; - что соотвевует второму вызову CreateDataSource - ТО ЕСТЬ произошло, как бы затирание подписки на колбек...<br />-НО ПОЧЕМУ ? Ведь я создал два разных &quot;потока&quot; которые хоть и связаныс основным луа-стеком, но сами обладают свои стеком, в который я и записываю результа от CreateDataSource.</p><p>Что то не понятно.</p>]]></description>
			<author><![CDATA[null@example.com (Serg_)]]></author>
			<pubDate>Sat, 15 Oct 2022 16:28:19 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?id=416&amp;action=new</guid>
		</item>
		<item>
			<title><![CDATA[Отписка callback`а SetUpdateCallbackcallback - отписывает ВСЕ заказы]]></title>
			<link>https://quik2dde.ru/viewtopic.php?id=414&amp;action=new</link>
			<description><![CDATA[<p>После вызова callback`а от SetUpdateCallback - я сразу отписываюсь от callback`а, но отписываюсь именно от как бы первого объекта CreateDataSource, но почему от отписка происходит от всех последующих от CreateDataSource.</p><br /><br /><p>Вот такой простенький код:</p><br /><br /><div class="codebox"><pre><code>function my_callback_CreateDataSource_HISTORY(my_table_data_history_candle_, code_class, code_paper, interval)

message(&quot;SIZE_TABLE:&quot; ..tostring(my_table_data_history_candle_:Size()) )

my_table_data_history_candle_:Close()     --отписываемся от callback`а. Нужен только первый вызов.

end


function my_callback_CreateDataSource_HISTORY_1(my_table_data_history_candle_, code_class, code_paper, interval)

message(&quot;SIZE_TABLE:&quot; ..tostring(my_table_data_history_candle_:Size()) )

--Этот колбек уже не вызывается.

end






function main()

local code_class_= &quot;TQBR&quot;          
local code_paper_= &quot;ZVEZ&quot;           
local interval_= INTERVAL_W1

my_table_, error_desc = CreateDataSource(code_class_, code_paper_, interval_)  

------------------------Проверка на ошибки:-------------------
if error_desc ~= nil then 
message(error_desc)
end
--------------------------------------------------------------

my_table_:SetUpdateCallback(function(idx)my_callback_CreateDataSource_HISTORY(my_table_, code_class_, code_paper_, intervakla_) end)




code_class_= &quot;TQBR&quot;          
code_paper_= &quot;ZVEZ&quot;           
interval_= INTERVAL_M15   


my_table_1, error_desc_1 = CreateDataSource(code_class_, code_paper_, interval_) 

------------------------Проверка на ошибки:-------------------
if error_desc_1 ~= nil then 
message(error_desc_1)
end
--------------------------------------------------------------

my_table_1:SetUpdateCallback(function(idx)my_callback_CreateDataSource_HISTORY_1(my_table_1, code_class_, code_paper_, intervakla_) end)



-------------------------
while not stopped do 
sleep(1)
end 
-------------------------


end -- end main()</code></pre></div><br /><p>То есть я вызываю CreateDataSource для двух значений, которые точно нужно заказывать на сервере.</p><p>На два значений вешаю callback`и.</p><p>Вызывается первый callback для my_table_ и сразу же отписываюсь от callback`а - НО отписка осуществляется и для таблицы my_table_1, то есть отписка осуществляется для всех ранее заказанных callback`ов для разных парамтеров.</p><p>Так и должно быть ?</p>]]></description>
			<author><![CDATA[null@example.com (Serg_)]]></author>
			<pubDate>Fri, 14 Oct 2022 18:30:29 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?id=414&amp;action=new</guid>
		</item>
		<item>
			<title><![CDATA[Передать в SetUpdateCallback дополнительные параметры №2]]></title>
			<link>https://quik2dde.ru/viewtopic.php?id=413&amp;action=new</link>
			<description><![CDATA[<p>Все таки не понятно, как же передать доп. параметры именно в callback.</p><p>Ну вот таким образом через lua_pushcclosure - я могу передать доп. параметры в просто функцию:</p><div class="codebox"><pre><code>static int my_pushcclosure_func(lua_State* L)
{
    std::cout &lt;&lt; &quot;Size_L:&quot; &lt;&lt;gettop(L) &lt;&lt; std::endl;    //Размер равен нулю.

    std::cout &lt;&lt; &quot;PARAM1:&quot; &lt;&lt; lua_tostring(L, lua_upvalueindex(1)) &lt;&lt; std::endl;    //Тут будет param1
    std::cout &lt;&lt; &quot;PARAM2:&quot; &lt;&lt; lua_tostring(L, lua_upvalueindex(2)) &lt;&lt; std::endl;    //Тут будет param2
}



    lua_pushstring(L, &quot;param1&quot;);
    lua_pushstring(L, &quot;param2&quot;);
    lua_pushcclosure(L, my_pushcclosure_func, 2);

    int status_lua_pcall = lua_pcall(L, 0, 0, 0);  </code></pre></div><p>Это хорошо - это работает.</p><p>Но, как мне это реализовать именно при вызове SetUpdateCallback и указании callback функции ?<br />Вот этого, уже не могу понять - как вызов SetUpdateCallback и передачу в него callback функции соединить с использованием lua_pushcclosure.</p>]]></description>
			<author><![CDATA[null@example.com (Serg_)]]></author>
			<pubDate>Wed, 12 Oct 2022 20:40:18 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?id=413&amp;action=new</guid>
		</item>
		<item>
			<title><![CDATA[Квик ПАДАЕТ от простейшего кода]]></title>
			<link>https://quik2dde.ru/viewtopic.php?id=412&amp;action=new</link>
			<description><![CDATA[<p>Квик ПАДАЕТ от простейшего кода - тупо ЗАКРЫВАЕТСЯ:</p><p>В квике Lua-скрипт:</p><div class="codebox"><pre><code>function main()

Quik_Lua_connector= require(&quot;Quik_Lua_connector&quot;)    

Quik_Lua_connector.run_Cpp() 

-------------------------
while not stopped do 
sleep(1)
end 
-------------------------
end</code></pre></div><br /><p>То есть из Квика запускаю функцию run_Cpp из .dll:</p><br /><div class="codebox"><pre><code>static int run_Cpp(lua_State* Lua_main) 
{

lua_State* L = lua_newthread(Lua_main);

std::cout &lt;&lt; &quot;SIZE_MAIN_STACK:&quot; &lt;&lt; lua_gettop(Lua_main) &lt;&lt; std::endl;
lua_close(L);            //Квик тупо ЗАКРЫВАЕТСЯ
std::cout &lt;&lt; &quot;SIZE_MAIN_STACK:&quot; &lt;&lt; lua_gettop(Lua_main) &lt;&lt; std::endl;
}</code></pre></div><br /><p>На выполнении строчки кода lua_close(L) - квик просто закрывается и все.</p>]]></description>
			<author><![CDATA[null@example.com (Serg_)]]></author>
			<pubDate>Wed, 12 Oct 2022 16:45:52 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?id=412&amp;action=new</guid>
		</item>
		<item>
			<title><![CDATA[Создать новый стек Lua]]></title>
			<link>https://quik2dde.ru/viewtopic.php?id=411&amp;action=new</link>
			<description><![CDATA[<p>Час от часу не легче...</p><p>Есть такой простой код:</p><p>В квике Lua-скрипт:</p><div class="codebox"><pre><code>function main()

Quik_Lua_connector= require(&quot;Quil_Lua_connector_work_TEST&quot;)    

Quik_Lua_connector.TestFunc_run_WinConsole_for_dll()

Quik_Lua_connector.run_Cpp() 

-------------------------
while not stopped do 
sleep(1)
end 
-------------------------
end</code></pre></div><br /><p>В С++ соответственно:</p><div class="codebox"><pre><code>static int run_Cpp(lua_State* Lua_stek)
{

    lua_State* L = luaL_newstate();

    if (L == NULL)
    {
        std::cout &lt;&lt; &quot;L == NULL&quot; &lt;&lt; std::endl;    //Ошибки нет.
    }

lua_getglobal(L, &quot;CreateDataSource&quot;);           

lua_pushstring(L, &quot;TQBR&quot;);    
lua_pushstring(L, &quot;GAZP&quot;);         
lua_pushnumber(L, &quot;INTERVAL_MN1&quot;);                

std::cout &lt;&lt; &quot;Size_stack:&quot; &lt;&lt; lua_gettop(L) &lt;&lt; std::endl;   //Размер 4 - как и должно быть

int status_lua_pcall = lua_pcall(L, 3, 2, 0);   
    
if(status_lua_pcall  != 0)
{
std::cout&lt;&lt;&quot;Error&quot;&lt;&lt;std::endl;   //attempt to call a nil value
}

}</code></pre></div><p>То есть я хочу использовать не автоматически созданный при вызове функции run_Cpp - Lua стек, а создать свой новый - через luaL_newstate.</p><p>Стек создается, он не равен нулю.<br />В стек добавляются элементы - то есть он рабочий.<br />Но, как я вызываю lua_pcall - то lua_pcall завершается ошибкой &quot;attempt to call a nil value&quot;.</p><p>Со автоматически созданный стеком Lua_stek - никаких ошибок нет, все работает.</p><p>Что это может быть ?</p>]]></description>
			<author><![CDATA[null@example.com (Serg_)]]></author>
			<pubDate>Wed, 12 Oct 2022 15:34:35 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?id=411&amp;action=new</guid>
		</item>
		<item>
			<title><![CDATA[Передать в SetUpdateCallback дополнительные параметры]]></title>
			<link>https://quik2dde.ru/viewtopic.php?id=410&amp;action=new</link>
			<description><![CDATA[<p>И я опять с вопросом.</p><p>При вызове SetUpdateCallback по умолчанию передать туда доп. параметры нельзя:</p><br /><div class="codebox"><pre><code>function my_callback_(index)

--index - индекс свечи в таблице my_table, НО сама таблица по умолчанию не приходит, что просто дикость.

end


local my_table = CreateDataSource(code_class, code_paper_ interval)

my_table :SetUpdateCallback(my_callback_)</code></pre></div><br /><br /><p>Но, передать доп. параметры в callback - можно с помощью такой контракции, в данном случае я не знаю, что она означает на Lua, просто подсмотрел в интернете:</p><div class="codebox"><pre><code>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 = &quot;1&quot;
parametr_2 = &quot;2&quot;

my_table :SetUpdateCallback(function(idx)my_callback_(my_table,parametr_1, parametr_2, idx) end)</code></pre></div><p>И теперь параметры замечательно переданы в callback SetUpdateCallback.</p><br /><p>И вот подскажите пожалуйста, а можно ли подобное провернуть в Си ??</p>]]></description>
			<author><![CDATA[null@example.com (Serg_)]]></author>
			<pubDate>Tue, 11 Oct 2022 09:18:43 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?id=410&amp;action=new</guid>
		</item>
		<item>
			<title><![CDATA[SetUpdateCallback возвращает Lua-стек в котором нет таблицы]]></title>
			<link>https://quik2dde.ru/viewtopic.php?id=409&amp;action=new</link>
			<description><![CDATA[<p>Какая то странность.</p><p>Вызываю CreateDataSource их С++ с заведомо такими параметрами акций по которым в квике нет загруженных данных.</p><p>То есть CreateDataSource&nbsp; - возвращает пустую таблицу и я вызываю SetUpdateCallback:</p><br /><div class="codebox"><pre><code>        lua_getfield(L, index, &quot;SetUpdateCallback&quot;);                    //&quot;Извлекаем&quot; из &quot;таблицы&quot; функцию SetUpdateCallback.

    lua_pushvalue(L, index);                                        //Помещаем копию обьекта таблицы на вершину стека.

    lua_pushcfunction(L, my_callback_);                       //Помещаем имя Сишой callback функции таблицы на вершину стека.

    int status_lua_pcall = lua_pcall(L, 2, 0, 0);              //Реализую вызов метода SetUpdateCallback</code></pre></div><br /><br /><div class="codebox"><pre><code>static int my_callback_(lua_State* L)
{
    std::cout &lt;&lt; &quot;my_callback_:&quot; &lt;&lt; lua_gettop(L) &lt;&lt; std::endl;

    status = lua_isstring(L, 1);
    if (status == 1)
    {
          std::cout&lt;&lt; &quot;lua_isstring:&quot;&lt;&lt; lua_tostring(L,1) &lt;&lt; std::endl ;
    }
    return 0;
}</code></pre></div><br /><p>И с одной стороны все нормально, my_callback_ - вызывается, НО с другой стороны - я ожидаю там увидеть таблицу запалённую данными свечей, а приходит строка:</p><div class="codebox"><pre><code>1
2
3
4
5
6
...
итд</code></pre></div><p>Такое ощущение, как будто бы похоже на размер таблицы, но в какой то момент это число доходит до 3007 и после этого так и приходит 3007 с последующими вызовами my_callback_ .</p><p>Непосредственно в скрипте Lua в квике такой странности не наблюдается, все работает нормально.<br />Что это может быть ?</p>]]></description>
			<author><![CDATA[null@example.com (Serg_)]]></author>
			<pubDate>Mon, 10 Oct 2022 18:39:03 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?id=409&amp;action=new</guid>
		</item>
	</channel>
</rss>
