Форум » [x]Harbour » передача данных между программами » Ответить

передача данных между программами

MIKHAIL: Есть ли возможность передать данные другой программе в виде массива достаточно большого размера кроме как через файлы и не через сокеты ? Слышал о shared memory, есть в harbour примеры ?

Ответов - 18

Andrey: MIKHAIL пишет: массива достаточно большого размера Какой размер ? Может можно обойтись SendMessage() - при помощи сообщения WM_COPYDATA Смотреть пример в МиниГуи - \MiniGUI\SAMPLES\BASIC\IPC

MIKHAIL: Andrey пишет: Какой размер ? всего 200 - 500тыс элементов Я так понял можно передавать в сообщении текст или бинарные данные. Т.е. нужно преобразовать массив в json форму, затем наверное желательно упаковать и передать как бинарные данные ? Наверное все же проще через промежуточную базу...

PSP: MIKHAIL пишет: Наверное все же проще через промежуточную базу... Однозначно.


Andrey: MIKHAIL пишет: Наверное все же проще через промежуточную базу... Можно и через массив в файл: [pre2] HB_MemoWrit( "_Dim.log", HB_ValToExp(aDim) )[/pre2] А в другой проге считать из файла: [pre2] cStr := ALLTRIM( hb_MemoRead("_Dim.log") ) IF LEN(cStr) == 0 // пустой файл ELSE IF AT( "{", cStr ) > 0 .AND. AT( "}", cStr ) > 0 aDim := &cStr ELSE // строка не массив ENDIF ENDIF[/pre2] Кстати можно этот массив передать и через SendMessage() без преобразования в json, как обычную строку !

MIKHAIL: Andrey пишет: &cStr макрос ограничение по длине имеет... Кстати можно этот массив передать и через SendMessage() без преобразования в json, как обычную строку ! Это как ? и как из строки преобразовать можно пример ? При таком объеме данных это все медленно будет ИМХО Я думал что то вроде shared memory использовать... но если нет, то dbf все решает

Dima: я юзаю для этих целей FT_SAVEARR FT_RESTARR

Andrey: MIKHAIL пишет: макрос ограничение по длине имеет... Не знаю... MIKHAIL пишет: Это как ? и как из строки преобразовать можно пример ? Примерно так: [pre2] cStr := HB_ValToExp(aDim) // Transfer data to window "Server" - из \MiniGUI\SAMPLES\BASIC\IPC\demo-client.prg SendMessageData( hwnd, cStr, nID ) [/pre2] Как принять строку смотри demo-main.prg [pre2] .... IF nMsg == WM_COPYDATA // to get data cData := GetMessageData( lParam, @nDataID ) .... cStr := cData IF LEN(cStr) == 0 // пустая строка ELSE IF AT( "{", cStr ) > 0 .AND. AT( "}", cStr ) > 0 aDim := &cStr ELSE // строка не массив ENDIF ENDIF[/pre2]

SergKis: Andrey пишет Как принять строку смотри demo-main.prg Прием идет в MiniGui программе, gtvwt нет обработки сообщения WM_COPYDATA для приема, может не вижу и как добавить обработчик того сообщения не ясно. MIKHAIL пишет При таком объеме данных это все медленно будет ИМХО На сообщении WM_COPYDATA можно строить обмен командами и данными, т.е. например массив в цикле обрабатываем и по элементно сообщением передаем др. программе и ждем ответа (опять WM_COPYDATA), что данные обработаны (можем иметь код возврата обработки) и снова передаем след. элемент с ожиданием ответа и т.д. по всем элементам массива (базы). Т.е. имеем типа сервер и несколько клиентов и они общаются по WM_COPYDATA. Здесь все быстро. Насколько это надо вам, если "dbf все решает". Если, все таки, такой механизм нужен, то можно пробовать на базе примера MiniGui\Samples\Basic\MixedMode, там два окна одно hmg другое gtwvt (ваша задача) и можно в hmg часть добавить обработку wm_copydata, как писал Андрей

MIKHAIL: SergKis пишет: массив в цикле обрабатываем и по элементно сообщением передаем др. программе и ждем ответа Задача была подготовить данные и отдать в отдельный процесс, который независимо от основной программы отработал бы и выдал результат. Так как обработка занимает длительное время и с родительской программой может случиться все что угодно, завершение пользователем или падение по ошибке, результат будет в любом случае. Сейчас в фоновом режиме идет обработка, бывает не успевает закончить... Как решить задачу много вариантов, думал юзал кто shared memory Dima пишет: я юзаю для этих целей FT_SAVEARR FT_RESTARR где посмотреть примеры ?

fil: В принимающей проге (А) делаем класс своего окна. Тогда из проги донора (В) PostmMssage(хендл окна А, инфа). В методе обработки событий окна проги А ловим посланное и парсим

Dima: MIKHAIL core-master\contrib\hbnf\doc\en\savearr.txt

Dima: MIKHAIL пишет: и не через сокеты А что нормальный вариант тоже , минуя файлы на диске. Можно попробовать организовать передачу массива через HBNETIO. В программе B (в отдельном потоке) организуешь работу RPC сервера через netio_mtserver() +твоя функция которая будет принимать массив и что то с ним делать. В программе A подключаемся к RPC серверу и выполняем удаленно твою функцию из программы B с передачей массива. Клиентские функции это позволяют , вот они на выбор: netio_ProcExec netio_ProcExecW netio_FuncExec

MIKHAIL: Dima пишет: я юзаю для этих целей FT_SAVEARR FT_RESTARR пробнул, для моих задач вполне подходит, 4мб файл получается за 5 секунд сохраняет на SSD и считывает так же. Спасибо!

Haz: MIKHAIL пишет: пробнул, для моих задач вполне подходит, Есть два момента 1)появление файла в цикле по таймеру проверять, работает конечно, но не технично 😎 2)к файлам любят придираться антивирусы. У меня на сервере один злой живет, создашь временный и не удалить пока он его не препарирует. Имхо через сообщения окну красивее, и сразу в json. Принимающая программа этот json в hash массив преобразует и ищи уже как хочешь, можно по индексу, можно по ключу. И к структуре массива не привязан, можно передавать любое количество элементов. Есть еще один экзотический способ передачи данных. Это так называемый pipe- запись в стандартное устройство ввода/вывода процесса. По сути работа с файлами без файлов на диске. Мне этот способ не зашел, но кто знает может есть любители.

Pasha: Вместо файла можно использовать dbf с memo-полем Передающая программа создает запись, может отметить время создания, и пишет данные в memo Принимающая программа проверяет, есть ли свежие данные, если есть - считывает их и удаляет запись Облегчается процедура проверки наличия данных, и зря не беспокоится антивирус

Pasha: да, для сохранения массива можно использовать вместо функций FT_SAVEARR FT_RESTARR функции hb_Serialize, hb_deserialize

Dima: Pasha пишет: да, для сохранения массива можно использовать вместо функций FT_SAVEARR FT_RESTARR функции hb_Serialize, hb_deserialize Для кодирования и записи в файл какими то средствами да , ведь сами по себе hb_Serialize, hb_deserialize не пишут/считывают в файл/файла

SergKis: Dima пишет ведь сами по себе hb_Serialize, hb_deserialize не пишут/считывают в файл/файл Есть интересная особенность (json не обязателен)[pre2] ... hConf[ "__signature" ] := _NETIOSRV_SIGNATURE hConf[ "__version" ] := 1 hConf[ "srv.showconn" ] := netiosrv[ _NETIOSRV_lShowConn ] hConf[ "srv.allow" ] := netiosrv[ _NETIOSRV_hAllow ] hConf[ "srv.block" ] := netiosrv[ _NETIOSRV_hBlock ] hConf[ "mgm.showconn" ] := netiomgm[ _NETIOSRV_lShowConn ] hConf[ "mgm.allow" ] := netiomgm[ _NETIOSRV_hAllow ] hConf[ "mgm.block" ] := netiomgm[ _NETIOSRV_hBlock ] RETURN hb_MemoWrit( netiosrv_ConfName(), hb_Serialize( hConf ) ) STATIC FUNCTION netiosrv_ConfLoad( netiosrv, netiomgm ) LOCAL hConf := hb_Deserialize( hb_MemoRead( netiosrv_ConfName() ) ) ... [/pre2]



полная версия страницы