Форум: "Начинающим";
Текущий архив: 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