Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.118.120.204] |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
один знакомый написал русский парсер, и оформил его в виде dll. ну, т е у него есть какая-то демка и игра, оболочка и т п,
НО меня интересует именно dll. и именно использование её на Delphi. к сожалению, он пишет на Си, и не может мне толком помочь. вот мой с ним диалог: noname Цитата отсюда вопрос: как прикрутить tom.dll к моей проге? ASBer Цитата На Си я это делаю так: Глобальные переменные: //переменные для текстового движка HINSTANCE EngineDll; typedef char*(*EngineFn)(char*); EngineFn RunFile=0; EngineFn RunText=0; EngineFn Command=0; EngineFn NormText=0; При старте программы: //загружаем движок EngineDll=GetModuleHandle("tom.dll"); if(!EngineDll) EngineDll=LoadLibrary("tom.dll"); if(!EngineDll) { PutStr("<font color=red>Не удалось загрузить tom.dll!\n<pause>"); return 0; } //получаем функции RunFile=(EngineFn)GetProcAddress(EngineDll,"@RunFile$qpc"); RunText=(EngineFn)GetProcAddress(EngineDll,"@RunText$qpc"); Command=(EngineFn)GetProcAddress(EngineDll,"@Command$qpc"); NormText=(EngineFn)GetProcAddress(EngineDll,"@NormText$qpc"); if(!RunFile||!RunText||!Command||!NormText) { PutStr("<font color=red>Не найдены функции tom.dll!\n<pause>"); return 0; } в процессе: char*Str=Command(input); при закрытии программы: //освобождаем движок FreeLibrary(EngineDll); GetModuleHandle(), LoadLibrary(), GetProcAddress(), FreeLibrary() - функции WinAPI. На паскале никогда не писал, тут я не помощник... hmm я, блин, и на Delphi-то не очень, а понять что здесь написано, и использовать tom.dll в своей проге- тем более сложно. там всего-то одно окно да один edit. уже имеющиеся под ТОМ оболочки меня не устраивают: одна из них- досовское текстовое окошко, с другой чё-та сильно заморочено. другую писал другой автор для своего движка, и сделал заодно возможность использовать ТОМ. --- ну, короче, думаю, суть вопроса ясна. |
Сообщ.
#2
,
|
|
|
Цитата ya2500 @ char*Str=Command(input); Угу. Насколько я понимаю, все функции возвращают строку. Здесь сразу проблема в освобождении выделенной памяти. Можешь попросить его экспортировать еще и функцию вроде Free_it, которая просто освобождает выделенную под результат функции память? Иначе будут проблемы |
Сообщ.
#3
,
|
|
|
Пускай он тебе пропишет функции конкретно
например longInt GetMyAIstartAlianse(int AlianseIndex, bool InCurrentProcess); А ты в делфе Function GetMyAIstartAlianse(AlianseIndex:integer;InCurrentProcess:boolean):LONGINT;cdecl;stdcall; external 'DrugLIB.dll'; И примерно вв таком темпе эзайте функции. Пускай он тебе отдельно пропишет каждую функции по шаблону WIN32.API GetXXXXXXXX SetXXXXXXXX Добавлено //переменные для текстового движка typedef char*(*EngineFn)(char*); На Делфи type TEngineFn = integer;{или POINTER но нужно дорабатывать} var EngineDll: HINSTANCE; RunFile: TEngineFn =0; Command: TEngineFn =0; NormText: TEngineFn =0; В случае {или POINTER} тебе нужно будет ассигновать тип с реально существующим классом. Но проблема в: Цитата ya2500 @ я, блин, и на Delphi-то не очень, а понять что здесь написано, и использовать tom.dll По этому используй метод который я тебе описал выше. |
Сообщ.
#4
,
|
|
|
Цитата aster_x @ Пускай он тебе пропишет функции конкретно Цитата aster_x @ typedef char*(*EngineFn)(char*); На Делфи type TEngineFn = pointer; Вот не надо. Все функции описаны. И описаны совсем не так, а как функция с одним параметром PChar возвращающая PChar. Единственный вопрос что делать с результатом функции после его использования, для этого просто нужен экспорт еще одной функции примерно как void free_it(char*); |
Сообщ.
#5
,
|
|
|
Romkin++
|
Сообщ.
#6
,
|
|
|
Цитата Romkin @ Угу. Насколько я понимаю, все функции возвращают строку. Здесь сразу проблема в освобождении выделенной памяти. Можешь попросить его экспортировать еще и функцию вроде Free_it, которая просто освобождает выделенную под результат функции память? Иначе будут проблемы Цитата Romkin @ Единственный вопрос что делать с результатом функции после его использования, для этого просто нужен экспорт еще одной функции примерно как void free_it(char*); хорошо. я дам ему ссылку на эту тему, надеюсь он поймёт, что от него требуется. допустим, у меня простое приложение с одним едитом и одним мемо. я хочу строку с едита передать на обработку этой длл-ке, а результат поместить в мемо. и, собственно, простейшая оболочка- готова. дальше можно совершенствовать это дело как угодно. вопрос такой: что на Delphi будет соответствовать коду //переменные для текстового движка HINSTANCE EngineDll; typedef char*(*EngineFn)(char*); EngineFn RunFile=0; EngineFn RunText=0; EngineFn Command=0; EngineFn NormText=0; --- всё, пошёл давать ему ссылку. Добавлено Цитата Romkin @ кажется, в теме УЖЕ содержится ответ. осталось только его понять. буду думать. Вот не надо. Все функции описаны. И описаны совсем не так, а как функция с одним параметром PChar возвращающая PChar. |
Сообщ.
#7
,
|
|
|
Цитата ya2500 @ вопрос такой: что на Delphi будет соответствовать коду HINSTANCE EngineDll; // это хэндл (беззнаковое целое, т.е. обычный Cardinal), в Delphi описан как THandle typedef char*(*EngineFn)(char*); // это указатель на функцию (простую, не метод!), возвращающую PChar и принимающую как параметр тоже PChar, в Delphi решается как-то так: TEngineFn = function(arg: PChar): PChar; // дальше просто конкретные переменные, хранящие указатели на конкретные функции с такой сигнатурой EngineFn RunFile=0; EngineFn RunText=0; EngineFn Command=0; EngineFn NormText=0; смотри комментарии в коде |
Сообщ.
#8
,
|
|
|
Цитата Romkin @ Цитата (ya2500 @ Вчера, 17:03) char*Str=Command(input); Угу. Насколько я понимаю, все функции возвращают строку. Здесь сразу проблема в освобождении выделенной памяти. Можешь попросить его экспортировать еще и функцию вроде Free_it, которая просто освобождает выделенную под результат функции память? Иначе будут проблемы Освобождение выделенной памяти происходит при следующем вызове функций движка. Или при освобождении dll. Подразумевается что при следующем вызове функции результаты предыдущего вызова вам уже не нужны. |
Сообщ.
#9
,
|
|
|
Цитата ASBer @ Освобождение выделенной памяти происходит при следующем вызове функций движка. Или при освобождении dll. Подразумевается что при следующем вызове функции результаты предыдущего вызова вам уже не нужны. Интересный подход. ya2500, могу предложить использовать это в Делфи таким образом: unit UTom; interface uses Windows, SysUtils; type TTomFunc = function(P: PAnsiChar): PAnsiChar; cdecl; ETomWrapperError = class(Exception); TTomWrapper = class(TObject) protected FHLibrary: HMODULE; FRunFile: TTomFunc; FRunText: TTomFunc; FCommand: TTomFunc; FNormText: TTomFunc; function CallTomFunc(Func: TTomFunc; const Input: string): string; public constructor Create(const LibName: string = ''); destructor Destroy(); override; function RunFile(const Input: string): string; function RunText(const Input: string): string; function Command(const Input: string): string; function NormText(const Input: string): string; end; implementation resourcestring STomDllDefFilename = 'Tom.dll'; SRunFileFuncName = '@RunFile$qpc'; SRunTextFuncName = '@RunText$qpc'; SCommandFuncName = '@Command$qpc'; SNormTextFuncName = '@NormText$qpc'; SErrorLoadLibrary = 'Не удалось загрузить библиотеку "%s", ошибка %d'; SErrorGetFunctions = 'Не удалось найти функции бибилиотеки'; { TTomWrapper } constructor TTomWrapper.Create(const LibName: string); var TomFilename: string; begin inherited Create(); if (LibName <> '') then TomFilename := LibName else TomFilename := STomDllDefFilename; FHLibrary := LoadLibrary(PChar(TomFilename)); if (FHLibrary = 0) then raise ETomWrapperError.CreateFmt(SErrorLoadLibrary, [TomFilename, GetLastError()]); FRunFile := TTomFunc(GetProcAddress(FHLibrary, PChar(SRunFileFuncName))); FRunText := TTomFunc(GetProcAddress(FHLibrary, PChar(SRunTextFuncName))); FCommand := TTomFunc(GetProcAddress(FHLibrary, PChar(SCommandFuncName))); FNormText := TTomFunc(GetProcAddress(FHLibrary, PChar(SNormTextFuncName))); if ((@FRunFile = nil) or (@FRunText = nil) or (@FCommand = nil) or (@FNormText = nil)) then raise ETomWrapperError.Create(SErrorGetFunctions); end; destructor TTomWrapper.Destroy(); begin if (FHLibrary <> 0) then FreeLibrary(FHLibrary); inherited Destroy(); end; function TTomWrapper.CallTomFunc(Func: TTomFunc; const Input: string): string; var AnsiStr: AnsiString; begin Result := ''; if (@Func <> nil) then begin AnsiStr := AnsiString(Input); UniqueString(AnsiStr); AnsiStr := Func(PAnsiChar(AnsiStr)); Result := string(AnsiStr); end; end; function TTomWrapper.RunFile(const Input: string): string; begin Result := CallTomFunc(FRunFile, Input); end; function TTomWrapper.RunText(const Input: string): string; begin Result := CallTomFunc(FRunText, Input); end; function TTomWrapper.Command(const Input: string): string; begin Result := CallTomFunc(FCommand, Input); end; function TTomWrapper.NormText(const Input: string): string; begin Result := CallTomFunc(FNormText, Input); end; end. Применять например так: unit Unit1; interface uses Windows, SysUtils, Classes, Graphics, Controls, StdCtrls, Forms, UTom; type TForm1 = class(TForm) Edit1: TEdit; Button1: TButton; Label1: TLabel; procedure FormDestroy(Sender: TObject); procedure FormActivate(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private declarations } Tom: TTomWrapper; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormActivate(Sender: TObject); begin Tom := TTomWrapper.Create(); end; procedure TForm1.FormDestroy(Sender: TObject); begin Tom.Free(); end; procedure TForm1.Button1Click(Sender: TObject); begin Label1.Caption := 'Tom returns: "' + Tom.NormText(Edit1.Text) + '"';//например, NormText() end; end. Естественно не проверял, но где-то в этом духе. |
Сообщ.
#10
,
|
|
|
Romkin, Mr.Delphist - спасибо. кажется, я начинаю понимать.
короче, чтоб юзать эту dll нужно: - задать (указатели на?) 4-ре функции. у каждой и параметр и возвращаемое значение- указатель на строку(типа того). - загрузить dll. думаю, разберусь, как это делается на Delphi. - получить функции. т е - указатели на них. - как пользоваться этими функциями- разбораться не проблема. лишь бы разобраться в предыдущих пунктах. пока буду курить хелпы. галочку "вопрос решён" поставлю после того, как сделаю простейшую прогу, с использованием tom.dll. сейчас мне осталось разобраться с: - хэндлами и функциями, которые можно получить по указателю. (может занять какое-то время) - и загрузкой dll. (это должно быть элементарно) Добавлено arj99, ой тока увидел. щазз почитаю |
Сообщ.
#11
,
|
|
|
Цитата Romkin @ Вот не надо. Все функции описаны. И описаны совсем не так, а как функция с одним параметром PChar возвращающая PChar. Совершенно верно. Это обычные функции (не методы). В исходниках движка выглядят примерно так: __declspec(dllexport) char*Command(char*Input) { char*Result; ... return Result; } |
Сообщ.
#12
,
|
|
|
ya2500, забыл заметить - это набросок на скорую руку для Ansi-версий Делфи.
|
Сообщ.
#13
,
|
|
|
Самое простенькое просто присоединить библиотеку, сделав небольшие обертки. Правда, библиотека будет висеть постоянно:
unit TomLib; interface uses SysUtils; function RunFile(const FileStr: AnsiString): AnsiString; function RunText(const TextStr: AnsiString): AnsiString; function Command(const CommandStr: AnsiString): AnsiString; function NormText(const TextStr: AnsiString): AnsiString; implementation const TomLibName = 'tom.dll'; function TomRunFile(Str: PAnsiChar): PAnsiChar; cdecl; external TomLibName name '@RunFile$qpc'; function TomRunText(Str: PAnsiChar): PAnsiChar; cdecl; external TomLibName name '@RunText$qpc'; function TomCommand(Str: PAnsiChar): PAnsiChar; cdecl; external TomLibName name '@Command$qpc'; function TomNormText(Str: PAnsiChar): PAnsiChar; cdecl; external TomLibName name '@NormText$qpc'; function RunFile(const FileStr: AnsiString): AnsiString; var Str: AnsiString; begin //На всякий случай полная копия параметра Str := FileStr; UniqueString(Str); //Здесь копирование идет Result := TomRunFile(PAnsiChar(Str)); assert(Str = FileStr); end; function RunText(const TextStr: AnsiString): AnsiString; var Str: AnsiString; begin Str := TextStr; UniqueString(Str); Result := TomRunFile(PAnsiChar(Str)); assert(Str = TextStr); end; function Command(const CommandStr: AnsiString): AnsiString; var Str: AnsiString; begin Str := CommandStr; UniqueString(Str); Result := TomCommand(PAnsiChar(Str)); assert(Str = CommandStr); end; function NormText(const TextStr: AnsiString): AnsiString; var Str: AnsiString; begin Str := TextStr; UniqueString(Str); Result := TomNormText(PAnsiChar(Str)); assert(Str = TextStr); end; end. Цитата ASBer @ Освобождение выделенной памяти происходит при следующем вызове функций движка. Или при освобождении dll. Действительно оригинально |
Сообщ.
#14
,
|
|
|
Romkin опытный аксакал полностью скопировать строку я не подумал, а стоило бы.
Исправил UTom с этим дополнением в сообщении #9, теперь он вроде даже Unicode-ready. |
Сообщ.
#15
,
|
|
|
А вот что буквально написано в первом топике, врапперы оставил:
unit TomLib; interface uses Windows, SysUtils; type ETomError = class(Exception); function RunFile(const FileStr: AnsiString): AnsiString; function RunText(const TextStr: AnsiString): AnsiString; function Command(const CommandStr: AnsiString): AnsiString; function NormText(const TextStr: AnsiString): AnsiString; implementation const TomLibName = 'tom.dll'; type TomFunc = function(Str: PAnsiChar): PAnsiChar; cdecl; var TomLibHandle: HMODULE; TomRunFile: TomFunc = nil; TomRunText: TomFunc = nil; TomCommand: TomFunc = nil; TomNormText: TomFunc = nil; procedure InitTomLib; begin TomLibHandle := LoadLibrary(TomLibName); if TomLibHandle = 0 then raiseLastOSError; TomRunFile:= GetProcAddress(TomLibHandle, '@RunFile$qpc'); if not assigned(TomRunFile) then raiseLastOSError; TomRunText:= GetProcAddress(TomLibHandle, '@RunText$qpc'); if not assigned(TomRunText) then raiseLastOSError; TomCommand:= GetProcAddress(TomLibHandle, '@Command$qpc'); if not assigned(TomCommand) then raiseLastOSError; TomNormText:= GetProcAddress(TomLibHandle, '@NormText$qpc'); if not assigned(TomNormText) then raiseLastOSError; end; procedure UnloadTomLib; begin if TomLibHandle = 0 then FreeLibrary(TomLibHandle); end; procedure CheckFunc(Func: TomFunc); begin if not assigned(Func) then raise ETomError.Create('Функция недоступна'); end; function RunFile(const FileStr: AnsiString): AnsiString; var Str: AnsiString; begin //На всякий случай полная копия параметра Str := FileStr; UniqueString(Str); //Здесь копирование CheckFunc(TomRunFile); Result := TomRunFile(PAnsiChar(Str)); assert(Str = FileStr); end; function RunText(const TextStr: AnsiString): AnsiString; var Str: AnsiString; begin //На всякий случай полная копия параметра Str := TextStr; UniqueString(Str); //Здесь копирование CheckFunc(TomRunText); Result := TomRunText(PAnsiChar(Str)); assert(Str = TextStr); end; function Command(const CommandStr: AnsiString): AnsiString; var Str: AnsiString; begin //На всякий случай полная копия параметра Str := CommandStr; UniqueString(Str); //Здесь копирование CheckFunc(TomCommand); Result := TomCommand(PAnsiChar(Str)); assert(Str = CommandStr); end; function NormText(const TextStr: AnsiString): AnsiString; var Str: AnsiString; begin //На всякий случай полная копия параметра Str := TextStr; UniqueString(Str); //Здесь копирование CheckFunc(TomNormText); Result := TomNormText(PAnsiChar(Str)); assert(Str = TextStr); end; initialization InitTomLib; finalization UnloadTomLib; end. Ну понятно, если хочется грузить когда надо, то просто выставить InitTomLib и UnloadTomLib в интерфейс, и защита нужна. Добавлено Цитата arj99 @ Исправил UTom с этим дополнением в сообщении #9, теперь он вроде даже Unicode-ready. CallTomFunc: в 80й строке ошибка, PAnsiChar нужен вместо PChar. А во-вторых, смысла особого не имеет подавать юникод, лучше просто оформить все в ansi. Оно все равно преобразуется в него при вызове. [DCC Warning] UTom.pas(78): W1058 Implicit string cast with potential data loss from 'string' to 'AnsiString' [DCC Warning] UTom.pas(81): W1057 Implicit string cast from 'AnsiString' to 'string' |