В статье "Обмен данными между DLL (C/C++) и приложением C#" показан простой пример отправки сообщений из DLL в приложение C#, а QUIK(Lua) просто запускает и останавливает эту отправку. Для отправки команд из приложения C# в QUIK лучше использовать примерно следующую конструкцию:
QLua-функция main()
-- с периодичность в 1 миллисекунду проверяет не пришла ли команда из C# function main() while IsRun do -- Если функция вернула не пустую строку local CommandStr = tostring(QluaCSharpConnector.GetCommand()); if CommandStr ~= "" then -- здесь будет Ваш код обработки команды end; sleep(1); end; end; |
DLL-функция (C/C++) GetCommand()
(Если Вы не знаете как создавать библиотеки DLL, которые можно использовать в скриптах QLua(Lua), ознакомьтесь, пожалуйста, с данной статьей).
// Имя для выделенной памяти TCHAR Name[] = TEXT("QUIKCommand"); // Создаст, или подключится к уже созданной памяти с таким именем HANDLE hFileMapQUIKCommand= CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 256, Name); static int forLua_GetCommand(lua_State *L) { //Если указатель на память получен if (hFileMapQUIKCommand) { //Получает доступ к байтам памяти PBYTE pb = (PBYTE)(MapViewOfFile(hFileMapQUIKCommand, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 256)); //Если доступ к байтам памяти получен if (pb != NULL) { //Если память чиста if (pb[0] == 0) { //Записывает в Lua-стек пустую строку lua_pushstring(L, ""); } else //Если в памяти есть команда { //Записывает в Lua-стек полученную команду lua_pushstring(L, (char*)(pb)); //Стирает запись, чтобы повторно не выполнить команду for (int i = 0; i < 256; i++)pb[i] = '\0'; } //Закрывает представление UnmapViewOfFile(pb); } else lua_pushstring(L, "");//Если доступ к байтам памяти не был получен, записывает в Lua-стек пустую строку } else //Указатель на память не был получен { //Записывает в Lua-стек пустую строку lua_pushstring(L, ""); } //Функция возвращает записанное значение из Lua-стека (пустую строку, или полученную команду) return(1); } |
Код C#
...
// Создаст, или подключится к уже созданной памяти с таким именем public MemoryMappedFile MemoryQUIKCommand; // Создает поток для чтения StreamReader SR_QUIKCommand; // Создает поток для записи StreamWriter SW_QUIKCommand; |
...
//выделяет именованную память размером 256 байт для отправки КОМАНД в QUIK, создает потоки чтения/записи MemoryQUIKCommand = MemoryMappedFile.CreateOrOpen("QUIKCommand", 256, MemoryMappedFileAccess.ReadWrite); SR_QUIKCommand = new StreamReader(MemoryQUIKCommand.CreateViewStream(), System.Text.Encoding.Default); SW_QUIKCommand = new StreamWriter(MemoryQUIKCommand.CreateViewStream(), System.Text.Encoding.Default); |
...
//Функция отправки команды в QUIK ( вызов: SetQUIKCommandData("Ваша команда"); ), или очистки памяти, при вызове без параметров ( вызов: SetQUIKCommandData(); ) private void SetQUIKCommandData(string Data = "") { //Если нужно отправить команду if (Data != "") { //Дополняет строку команды "нулевыми байтами" до нужной длины for (int i = Data.Length; i < 256; i++) Data += "\0"; } else //Если нужно очистить память { //Заполняет строку для записи "нулевыми байтами" for (int i = 0; i < 256; i++) Data += "\0"; } //Встает в начало SW_QUIKCommand.BaseStream.Seek(0, SeekOrigin.Begin); //Записывает строку SW_QUIKCommand.Write(Data); //Сохраняет изменения в памяти SW_QUIKCommand.Flush(); } |
Здравствуйте!
Периодически вылетает ошибка: "Необработанное исключение по адресу
0x000007F9EC5C9D19 (ntdll.dll) в info.exe: 0xC0000374: Куча была повреждена
(параметры: 0x000007F9EC61E5F0)". Часто если в коде lua указано: "sleep(1)".
Ошибка чтения в точке "lua_pushstring(L, (char*)(pb))".
Как её избежать?
Microsoft Visual Studio Enterprise 2015
Версия 14.0.24720.00 Update 1
Microsoft .NET Framework
Версия 4.6.01055
я использовал lua5.1.lib
Простите, если не в том разделе вопрос задаю, более подходящего не сыскал. Пишу небольшую программку на С++, думаю она быстрее меня будет реагировать на некоторые события в Квике. И организовалась сложность, которую не смог победить. Вполне нормально получаю Хендлы всех нужных мне окон, Но Хендл окна диалога Ввода заявки, которое вызывается по F2, получить не получается. Может подскажете, может есть известный способ, как этот Хендл получить? Спасибо.
Похоже, не у кого не было такой задачи.
И все же вынесу этот вопрос в отдельный. Дмитрий, почему вы библиотеки пишете на C, а оконное приложение на C#? Это просто личное предпочтение, или на то есть объективные причины?
Здравствуйте! В C# мне комфортнее работать, а окна можно и в dll создавать, но мне не понравилось.
Я понимаю, что сейчас задам очень глупый вопрос, но не судите строго, я не разбираюсь в технологии и толком не могу объяснить разницу между подключаемой библиотекой и оконным приложением. Пусть это будет вопрос от новичков и для новичков.
Итак, имея ссылку на объект L мы можем очень просто из кода DLL-библиотеки на C++ вызывать любые функции LUA. Но если мы хотим это делать из оконного приложения на C++ или C# (не вижу принципиальной разницы. Или я не прав?) то мы должны использовать уже гораздо более сложные схемы с передачей строки команды, MMF, распарсивания этой команды и т.д. А можно ли создать оконное приложение внутри DLL-библиотеки? И тогда не нужны никакие MMF. Вот GUI-библиотеки, реализованные как DLL и написанные на C, создают же окна и формы. Почему мы так не можем, типа при подключении DLL к LUA-скрипту создается оконное приложение?