Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2009.09.27;
Скачать: [xml.tar.bz2];

Вниз

Как организовать scripting host плагин на делфи?   Найти похожие ветки 

 
tcler   (2009-07-20 00:14) [0]

здравствуйте. собственно, такая задача - написать плагин - прослойку для download master - скриптовый хост, хочется писать плагины для ДМ на пайтоне. вот только с какого бока к этой задаче подойти - непонятно, документации по этой теме в интернете не нашёл. надеюсь на помощь )


 
sniknik ©   (2009-07-20 01:06) [1]

> хочется писать плагины для ДМ на пайтоне. вот только с какого бока к этой задаче подойти - непонятно
ну и пиши. причем тут дельфи? на питоне можно писать как скрипты под апач (или другой сервер поддерживающий внешние скрипты), так и отдельно стоящий веб сервер (сервлет), который сам по себе и сервер и приложение.

или ты хочешь что-то типа апача на дельфи написать?


 
tcler   (2009-07-20 01:25) [2]

я разве упоминал веб-сервер? есть хороший, многим известный загрузчик - download master. вот для него я и хочу писать плагины на питоне. разумеется, для этого нужно сотворить прослойку - скриптовый хост, например(имеется реализация для far, вот только её исходники автор не опубликовал). это один из вариантов, надеюсь, мне посоветуют наиболее приемлемый :)


 
Германн ©   (2009-07-20 01:28) [3]


> есть хороший, многим известный загрузчик - download master.

Не знаю, Не пользуюсь.


 
sniknik ©   (2009-07-20 01:50) [4]

> вот для него я и хочу писать плагины на питоне.
а он их поддерживает? на питоне? или хотя бы вообще?

> для этого нужно сотворить прослойку - скриптовый хост
сам питон интерпретатор (python.exe)? ставишь питон на комп, регистрируешь расширение на выполнение им и готова "прослойка", можно прям из программы выполнять питоновские скрипты (например через ShellExecute).

> надеюсь, мне посоветуют наиболее приемлемый :)
пока непонятно, что именно ты делаешь, не посоветуют.

а что именно не понятно, т.к. объяснения вида "имеется реализация для far" ничего не объясняют, даже имея фар не понятно, что ты за "реализацию", чего и для чего, упомянул. что она делает тоже  ни о чем не говорит.

> Не знаю, Не пользуюсь.
аналогично.
и потому вместо того чтобы перечислять где то о чем ты думаешь есть, лучше бы сказал что хочешь.


 
tcler   (2009-07-20 02:02) [5]


> можно прям из программы выполнять питоновские скрипты (например
> через ShellExecute)

мне нужно написать плагин для программы на питоне. не выполнить какой-то скрипт. написать плагин. как мы знаем, плагин на питоне для нативной программы просто так не состряпать, бо язык не компилируемый. но написать его всё равно хочется, поэтому ищем обходные пути. например, пишем плагин на паскале для ДМ, который будет регистрировать скрипты-плагины на питоне и осуществлять прослойку между ДМ и интерпретатором питона. поскольку в программировании я пока нуб, непонятно, как лучше осуществить передачу событий, например. вот пример тестового плагина http://downloadmaster.ru/dm/download/dmtest_plugin.zip плагин апи в ДМ проще некуда. лучше объяснить не смогу, наверное, надеюсь на понимание :)


 
Германн ©   (2009-07-20 02:13) [6]


> как мы знаем, плагин на питоне для нативной программы просто
> так не состряпать

Я не знаю.

> поскольку в программировании я пока нуб

И ты не знаешь.
И куда тут нам с тобой деваться? (В оригинале было "куда крестьянину деваться :)

Я знаю только один путь. Тебе нужно учиться.


 
tcler   (2009-07-20 02:33) [7]


> Я не знаю.

а чего там знать? плагин - простая дллка, в случае с ДМ - просто экспортирующая информацию о себе и обрабатывающая события. впрочем, дело пахнет обыкновенным стёбом над новичком :) я понимаю, что мастерам чертоффски надоело тыкать нубов носом в простейшие вещи, но я ведь прошу не решение, а намёк хотя бы )


 
Германн ©   (2009-07-20 02:43) [8]


> впрочем, дело пахнет обыкновенным стёбом над новичком

Не правильно понимаешь.


 
sniknik ©   (2009-07-20 10:40) [9]

> впрочем, дело пахнет обыкновенным стёбом над новичком :) ... в простейшие вещи
тут пахнет далеко не простейшими вещами, если делать все именно так как ты описал. реализовать это будет сложно, может даже невозможно (дело в 1 плагине или ты под одним именем дельфевской dll хочешь регистрировать все что пишешь на питоне).
другое дело это может быть глупым, как и любое другое использование вещей не по назначению.

> но я ведь прошу не решение, а намёк хотя бы )
намек  
вместо
function TDMTestPlugIn.GetName: WideString;//получаем инфу о плагине
begin
 Result := myPluginName;
end;

должен быть вызов скрипта отдающего тебе имя плагина, и т.д. для всех методов

сам "плагин" будет выглядеть примерно так
#-*- coding: utf-8 -*-

import sys

##укажите здесь информацию о своем плагине
myPluginID = "{45145BBE-DCAE-4187-B981-FE9410F6DA5D}"  ##обязательно укажите свой уникальный номер плагина (используйте Ctrl+Shift+G для генерации)
myPluginName = "Download Master Test Plug-in"          ##название плагина на английском языке
myPluginVersion = "0.1.1.1"
myPluginEmail = "slava@westbyte.com"
myPluginHomePage = "http://www.westbyte.com/dm/"
myPluginCopyRight = chr(169)+"2006 WestByte"
myMinNeedAppVersion = "5.0.2";                         ##версия указывается без билда
##описание плагина. Должно быть представлено на русском и английском языках. Может содержать подробную инструкцию по пользованию плагином.
myPluginDescription = "Test Plug-in for show how create plugins for DM"
myPluginDescriptionRussian = "Тестовый плагин для демонстрации как создавать плагины для DM. Является одновременно шаблоном для создания плагинов. Язык реализации Delphi 7."

if sys.argv[1] == "id":
   print myPluginID
elif sys.argv[1] == "name":
   print myPluginName
elif sys.argv[1] == "version":
   print myPluginVersion
и т.д.

т.е. в зависимости от параметра он будет выдавать в output запрашиваемое значение, ты его будешь принимать из input консоли, и возвращать результат.
для событий будет 2 параметра, первый eventType = "dm_download_added" (как в примере), чтобы различать, во втором собственно данные.

читать вывод на консоль можно так (найдено в гугле, код не мой, скорее всего нужно переделать, и возможно можно оптимизировать)
procedure ExecConsoleApp(CommandLine: AnsiString; Output: TStringList; Errors:
 TStringList);
var
 sa: TSECURITYATTRIBUTES;
 si: TSTARTUPINFO;
 pi: TPROCESSINFORMATION;
 hPipeOutputRead: THANDLE;
 hPipeOutputWrite: THANDLE;
 hPipeErrorsRead: THANDLE;
 hPipeErrorsWrite: THANDLE;
 Res, bTest: Boolean;
 env: array[0..100] of Char;
 szBuffer: array[0..256] of Char;
 dwNumberOfBytesRead: DWORD;
 Stream: TMemoryStream;
begin
 sa.nLength := sizeof(sa);
 sa.bInheritHandle := true;
 sa.lpSecurityDescriptor := nil;
 CreatePipe(hPipeOutputRead, hPipeOutputWrite, @sa, 0);
 CreatePipe(hPipeErrorsRead, hPipeErrorsWrite, @sa, 0);
 ZeroMemory(@env, SizeOf(env));
 ZeroMemory(@si, SizeOf(si));
 ZeroMemory(@pi, SizeOf(pi));
 si.cb := SizeOf(si);
 si.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
 si.wShowWindow := SW_HIDE;
 si.hStdInput := 0;
 si.hStdOutput := hPipeOutputWrite;
 si.hStdError := hPipeErrorsWrite;

 (* Remember that if you want to execute an app with no parameters you nil the
    second parameter and use the first, you can also leave it as is with no
    problems.                                                                 *)
 Res := CreateProcess(nil, pchar(CommandLine), nil, nil, true,
   CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, @env, nil, si, pi);

 // Procedure will exit if CreateProcess fail
 if not Res then
 begin
   CloseHandle(hPipeOutputRead);
   CloseHandle(hPipeOutputWrite);
   CloseHandle(hPipeErrorsRead);
   CloseHandle(hPipeErrorsWrite);
   Exit;
 end;
 CloseHandle(hPipeOutputWrite);
 CloseHandle(hPipeErrorsWrite);

 //Read output pipe
 Stream := TMemoryStream.Create;
 try
   while true do
   begin
     bTest := ReadFile(hPipeOutputRead, szBuffer, 256, dwNumberOfBytesRead,
       nil);
     if not bTest then
     begin
       break;
     end;
     Stream.Write(szBuffer, dwNumberOfBytesRead);
   end;
   Stream.Position := 0;
   Output.LoadFromStream(Stream);
 finally
   Stream.Free;
 end;

 //Read error pipe
 Stream := TMemoryStream.Create;
 try
   while true do
   begin
     bTest := ReadFile(hPipeErrorsRead, szBuffer, 256, dwNumberOfBytesRead,
       nil);
     if not bTest then
     begin
       break;
     end;
     Stream.Write(szBuffer, dwNumberOfBytesRead);
   end;
   Stream.Position := 0;
   Errors.LoadFromStream(Stream);
 finally
   Stream.Free;
 end;

 WaitForSingleObject(pi.hProcess, INFINITE);
 CloseHandle(pi.hProcess);
 CloseHandle(hPipeOutputRead);
 CloseHandle(hPipeErrorsRead);
end;

(* got it from yahoo groups, so no copyrights for this piece :p and and example
  of how to use it. put a button and a memo to a form.                      *)

procedure TForm1.Button1Click(Sender: TObject);
var
 OutP: TStringList;
 ErrorP: TStringList;
begin
 OutP := TStringList.Create;
 ErrorP := TstringList.Create;

 ExecConsoleApp("ping localhost", OutP, ErrorP);
 Memo1.Lines.Assign(OutP);

 OutP.Free;
 ErrorP.Free;
end;

можешь поискать другой пример, их полно.


 
tcler   (2009-07-20 14:28) [10]

большое спасибо за помощь. вот только постоянные перезапуски питонового скрипта при возникновении событий - не вариант. как можно оптимально передавать события в запущенный скрипт, не подскажете?


 
sniknik ©   (2009-07-20 14:48) [11]

можно еще например написать на питоне программу сервер/севлет по типу веба (см. [1]) которая будет "висеть" в рабочем режиме постоянно и обрабатывать запросы от твоей dll на дельфи, общаться они могут по какому нибудь протоколу (да тот же http пойдет, тем более для него уже все есть)...
только, ИМХО, такая схема получится гораздо более громоздкая и более медленная чем "постоянные перезапуски питонового скрипта". (ИМХО потому как надо бы проверить чтобы быть уверенным)


 
tcler   (2009-07-20 14:54) [12]

наткнулся тут на такую вещь, как named pipes. через ctypes на питоне c этими каналами можно работать. по первому впечатлению от прочитанной информации - то что надо. я не ошибаюсь, для моей задачи pipes подойдут?


 
sniknik ©   (2009-07-20 15:14) [13]

без разницы, протокол/транспорт обмена данными значения не имеет. хочешь pipes ну пусть будут pipes.
http предложил только потому, что там уже есть готовые сервера(/компоненты) под него. т.е. было бы чуть проще.
можно еще memory mapped file/tcp-ip/raw socket/ и вообще, что угодно на что фантазии хватит.


 
tcler   (2009-07-20 15:22) [14]

понял, спасибо за консультацию, буду разбираться.


 
tcler   (2009-07-22 00:38) [15]

остановился на варианте с sharing memory, подкупила простая реализация. на данный момент скрипты-плагины инициализируются нормально, но дальше беда - нужен какой-то способ залочки процессом участка памяти на время чтения/записи, а то может(и наверняка случится) страшное. мутекс вроде бы подходит, но непонятен механизм блокировки - как он осуществляется? в примерах указывается создание мутекса(CreateMutex), его освобождение (ReleaseMutex), ожидание разблокировки через WaitForSingleObject(), а как его заблокировать? или просто тыкните носом в нормальную статью для нубов :)



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2009.09.27;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.004 c
15-1248439811
Kolan
2009-07-24 16:50
2009.09.27
Нет ли у кого файла D2XXUnit.pas для Делфи 2009?


15-1248936484
123123
2009-07-30 10:48
2009.09.27
rsync


15-1248873578
Reactor
2009-07-29 17:19
2009.09.27
Подскажите про трасерт


2-1248451922
Альберт
2009-07-24 20:12
2009.09.27
Работа с time_t


1-1216800759
artkil
2008-07-23 12:12
2009.09.27
Unicode в Delphi через TntListBox





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский