Есть интерфейс для взаимодействия с библиотекой. Примерно такой:
=== Starting UnRAR.pas ===
{$IFDEF Open32}
{&cdecl+}
{$ELSE}
{&StdCall+}
{$ENDIF Open32}
{&AlignRec+,SmartLink+,OrgName+,X+,Z+,Use32-}
unit UnRAR;
interface
[...]
function RAROpenArchive(var ArchiveData: RAROpenArchiveData): THandle;
[...]
implementation
function RAROpenArchive(var ArchiveData: RAROpenArchiveData): THandle;
external 'unrar.dll' name 'RAROpenArchive';
[...]
end.
=== End of UnRAR.pas ===
Есть программа, которая юзает этот юнит:
=== Starting rartest.pas ===
uses
Windows,
Strings,
UnRAR;
var
Data: RAROpenArchiveData;
HeaderData: RARHeaderData;
Handle: THandle;
PathBuf: array[0..255] of Char;
N: Longint;
begin
FillChar(Data, SizeOf(Data), #0);
Data.ArcName := StrPCopy(@PathBuf, 'test.rar');
Data.OpenMode := RAR_OM_EXTRACT;
Data.CmtBuf := nil;
Handle := RAROpenArchive(Data);
WriteLn('Open archive result: ', Data.OpenResult);
if Data.OpenResult = 0 then
repeat
FillChar(HeaderData, SizeOf(HeaderData), #0);
N := RARReadHeader(Handle, HeaderData);
if N = 0 then
begin
Write('Testing ' + StrPas(HeaderData.FileName) + '..');
if RARProcessFile(Handle, RAR_TEST, nil, nil) = 0 then
WriteLn('OK')
else
WriteLn('FAIL');
end;
until N <> 0;
RARCloseArchive(Handle);
end.
=== End of rartest.pas ===
Программа нормально собирается и работает, если собирать с ключом -b. Если
собирать с ключом -m, программа не запускается, если юнит UnRAR был
скомпилирован до этого. Если поглядеть в код программы, в ней вообще
отсутствует упоминание об unrar.dll. Это глюк компилятора? Или фича? Или я
что-то не так делаю?
Еще есть предположение, что этот эффект можно победить, создав библиотеку
импорта, как это сделано для kernel32.dll и прочих стандартных. Hо это какой-то
ненормальный путь, мне кажется.
И еще, очень интересный момент. Если добавить {$D+} в UnRAR.pas - проблема
исчезает. Мистика какая-то.
ЗЫ: настройки компилятора:
=== Starting |vpcc ===
AlignCode- Code alignment Open32- Open32 compatibility
AlignData- Data alignment Optimise+ Enable optimisations
AlignRec- Field alignment OrgName- Original names
Asm- Assembler output P- Open string params
B- Full boolean eval PureInt- Pure interface unit
Cdecl- C language calls Q- Overflow checking
Comments- Nested comments R- Range checking
D- Debug information S- Stack checking
Delphi+ Enable Delphi syntax SmartLink+ Create .LIB file
Far16- Far16 Pascal calls Speed- Optimise for speed
Frame+ Stack frame for asm subprgs StdCall- StdCall calls
G3- 386 instructions T- Typed pointers
G4- 486 instructions Use32- Include Use32 unit
G5+ P5 instructions V+ Strict var-strings
H- Huge strings W- Generate stack frames
I- I/O error checking X+ Extended syntax
J+ Writable consts Z- DWord-sized enums
LocInfo- Location information Zd- Line numbers in .OBJ/.LIB
M- Runtime type info
=== End of |vpcc ===
02 Dec 05 21:55, Alexey Fayans wrote to All:
AF> Программа нормально собирается и работает, если собирать с ключом -b.
AF> Если собирать с ключом -m, программа не запускается, если юнит UnRAR
AF> был скомпилирован до этого. Если поглядеть в код программы, в ней
AF> вообще отсутствует упоминание об unrar.dll. Это глюк компилятора? Или
AF> фича? Или я что-то не так делаю?
Это "фича" компилятора. Он не сохраняет в юнитах упоминание о dll.
AF> Еще есть предположение, что этот эффект можно победить, создав
AF> библиотеку импорта, как это сделано для kernel32.dll и прочих
AF> стандартных. Hо это какой-то ненормальный путь, мне кажется.
Ага. Вот именно так и лечится. Пишешь
function RAROpenArchive(var ArchiveData: RAROpenArchiveData):THandle;
external;
и подключаешь в юнит библиотеку: {$L UNRAR.LIB}
Dmitry.
AF> === Starting UnRAR.pas ===
AF> {$IFDEF Open32}
AF> {&cdecl+}
AF> {$ELSE}
AF> {&StdCall+}
AF> {$ENDIF Open32}
Это вообще практически бесполезные ключи.
AF> {&AlignRec+,SmartLink+,OrgName+,X+,Z+,Use32-}
AF> unit UnRAR;
AF> interface
AF> [...]
AF> function RAROpenArchive(var ArchiveData: RAROpenArchiveData): THandle;
AF> [...]
AF> implementation
AF> function RAROpenArchive(var ArchiveData: RAROpenArchiveData): THandle;
AF> external 'unrar.dll' name 'RAROpenArchive';
Ты уверен, что нет проблем со стэком?
Тут не указано cdecl или stdcall;
unrardll написан под паскаль? Тот же алигн структур?
AF> [...]
AF> end.
AF> === End of UnRAR.pas ===
AF> Есть программа, которая юзает этот юнит:
AF> === Starting rartest.pas ===
AF> uses
AF> Windows,
AF> Strings,
AF> UnRAR;
AF> var
AF> Data: RAROpenArchiveData;
AF> HeaderData: RARHeaderData;
AF> Handle: THandle;
AF> PathBuf: array[0..255] of Char;
AF> N: Longint;
AF> begin
AF> FillChar(Data, SizeOf(Data), #0);
AF> Data.ArcName := StrPCopy(@PathBuf, 'test.rar');
AF> Data.OpenMode := RAR_OM_EXTRACT;
AF> Data.CmtBuf := nil;
AF> Handle := RAROpenArchive(Data);
AF> WriteLn('Open archive result: ', Data.OpenResult);
AF> if Data.OpenResult = 0 then
AF> repeat
AF> FillChar(HeaderData, SizeOf(HeaderData), #0);
AF> N := RARReadHeader(Handle, HeaderData);
AF> if N = 0 then
AF> begin
AF> Write('Testing ' + StrPas(HeaderData.FileName) + '..');
AF> if RARProcessFile(Handle, RAR_TEST, nil, nil) = 0 then
AF> WriteLn('OK')
AF> else
AF> WriteLn('FAIL');
AF> end;
AF> until N <> 0;
AF> RARCloseArchive(Handle);
AF> end.
AF> === End of rartest.pas ===
AF> Программа нормально собирается и работает, если собирать с ключом -b.
Что за ключ?
AF> Если собирать с ключом -m,
Что за ключ?
AF> программа не запускается, если юнит UnRAR
AF> был скомпилирован до этого. Если поглядеть в код программы, в ней
AF> вообще отсутствует упоминание об unrar.dll. Это глюк компилятора? Или
AF> фича? Или я что-то не так делаю?
Какую ошибку выводит?
unrar.dll не может отсутсвовать, он должен быть в importtable.
AF> Еще есть предположение, что этот эффект можно победить, создав
AF> библиотеку импорта, как это сделано для kernel32.dll и прочих
AF> стандартных. Hо это какой-то ненормальный путь, мне кажется.
AF> И еще, очень интересный момент. Если добавить {$D+} в UnRAR.pas -
AF> проблема исчезает. Мистика какая-то.
AF> ЗЫ: настройки компилятора:
[ ... decrypted by Sp0Raw ... ]
On 03 Dec 2005 02:05 you wrote me:
AF>> Программа нормально собирается и работает, если собирать с ключом
AF>> -b. Если собирать с ключом -m, программа не запускается, если
AF>> юнит UnRAR был скомпилирован до этого. Если поглядеть в код
AF>> программы, в ней вообще отсутствует упоминание об unrar.dll. Это
AF>> глюк компилятора? Или фича? Или я что-то не так делаю?
DZ> Это "фича" компилятора. Он не сохраняет в юнитах упоминание о dll.
Плохая фича.. Ладно, будем извращаться.. Спасибо. :)
Кстати, а $L писать обязательно? Мне казалось, будет достаточно этот либ просто
положить в %VPBase%\lib.w32.
On 03 Dec 2005 02:51 you wrote me:
AF>> === Starting UnRAR.pas ===
AF>> {$IFDEF Open32}
AF>> {&cdecl+}
AF>> {$ELSE}
AF>> {&StdCall+}
AF>> {$ENDIF Open32}
SR> Это вообще практически бесполезные ключи.
Именно таким образом сделано в юните windows.
[...]
AF>> function RAROpenArchive(var ArchiveData: RAROpenArchiveData):
AF>> THandle;
AF>> external 'unrar.dll' name 'RAROpenArchive';
SR> Ты уверен, что нет проблем со стэком?
SR> Тут не указано cdecl или stdcall;
Оно задано глобально для всего файла. Если бы calling convention был
стандартный, были бы перепутаны параметры. А у меня все работает. :)
SR> unrardll написан под паскаль? Тот же алигн структур?
Я просто немного переделал дельфийный модуль, который шел в комплекте.
Структуры по крайней мере передаются как надо.
AF>> Программа нормально собирается и работает, если собирать с ключом
AF>> -b.
SR> Что за ключ?
build all
AF>> Если собирать с ключом -m,
SR> Что за ключ?
make modified
AF>> программа не запускается, если юнит UnRAR
AF>> был скомпилирован до этого. Если поглядеть в код программы, в ней
AF>> вообще отсутствует упоминание об unrar.dll. Это глюк компилятора?
AF>> Или фича? Или я что-то не так делаю?
SR> Какую ошибку выводит?
RTE216 или вообще ошибку инициализации.
SR> unrar.dll не может отсутсвовать, он должен быть в importtable.
HЕТУ ЕГО ТАМ. Причем только если собирать второй раз, не пересобирая UnRAR.pas.
On 03 Dec 2005 09:02 I wrote you:
AF> Кстати, а $L писать обязательно? Мне казалось, будет достаточно этот
AF> либ просто положить в %VPBase%\lib.w32.
Ага, уже вижу, что обязательно.
Эти ключи не влияют на external объекты.
AF> [...]
AF>>> function RAROpenArchive(var ArchiveData: RAROpenArchiveData):
AF>>> THandle;
AF>>> external 'unrar.dll' name 'RAROpenArchive';
SR>> Ты уверен, что нет проблем со стэком?
SR>> Тут не указано cdecl или stdcall;
AF> Оно задано глобально для всего файла. Если бы calling convention был
AF> стандартный, были бы перепутаны параметры. А у меня все работает. :)
SR>> unrardll написан под паскаль? Тот же алигн структур?
AF> Я просто немного переделал дельфийный модуль, который шел в комплекте.
AF> Структуры по крайней мере передаются как надо.
AF>>> Программа нормально собирается и работает, если собирать с
AF>>> ключом -b.
SR>> Что за ключ?
AF> build all
AF>>> Если собирать с ключом -m,
SR>> Что за ключ?
AF> make modified
AF>>> программа не запускается, если юнит UnRAR
AF>>> был скомпилирован до этого. Если поглядеть в код программы, в
AF>>> ней вообще отсутствует упоминание об unrar.dll. Это глюк
AF>>> компилятора? Или фича? Или я что-то не так делаю?
SR>> Какую ошибку выводит?
AF> RTE216 или вообще ошибку инициализации.
SR>> unrar.dll не может отсутсвовать, он должен быть в importtable.
AF> HЕТУ ЕГО ТАМ. Причем только если собирать второй раз, не пересобирая
AF> UnRAR.pas.
Hу тебе вроде тут ответили чего-то. Хотя мне проблема не понятна :(
В чем глюк? Что-то я не понимаю сути проблемы :)
AF>> Еще есть предположение, что этот эффект можно победить, создав
AF>> библиотеку импорта, как это сделано для kernel32.dll и прочих
AF>> стандартных. Hо это какой-то ненормальный путь, мне кажется.
DZ> Ага. Вот именно так и лечится. Пишешь
DZ> function RAROpenArchive(var ArchiveData:
DZ> RAROpenArchiveData):THandle;
DZ> external;
DZ> и подключаешь в юнит библиотеку: {$L UNRAR.LIB}
To AF: предлагаю уйти от этого изврата и сделать динамическую линковку через
LoadLibrary/GetProcAddress
On 03 Dec 2005 15:26 you wrote Dmitry Zavalskov:
SR> To AF: предлагаю уйти от этого изврата и сделать динамическую линковку
SR> через LoadLibrary/GetProcAddress
Hадо будет подумать над этим.. Может и вторая проблема таким образом решится..
On 03 Dec 2005 15:26 you wrote Dmitry Zavalskov:
DZ>> Это "фича" компилятора. Он не сохраняет в юнитах упоминание о
DZ>> dll.
SR> В чем глюк? Что-то я не понимаю сути проблемы :)
Глюк в том, что в отлинкованном модуле, в котором прописаны функции dll как
external 'dllname.dll', не сохраняется упоминание о dll, которой эти функции
пренадлежат. И программа, собранная с таким юнитом, попросту неработоспособна.
On 03 Dec 2005 15:27 you wrote me:
SR>>> Это вообще практически бесполезные ключи.
AF>> Именно таким образом сделано в юните windows.
SR> Эти ключи не влияют на external объекты.
Дубль два. Именно так сделано в RTL модуле windows.pas. Там все виндовые
функции объявлены без модификатора stdcall. Hо я на всякий случай сделал как ты
говоришь, прописал везде stdcall - абсолютно то же самое. В любом случае,
модификатор stdcall можно прописывать только в интерфейсной части юнита. Ибо:
UnRAR.pas(148): Error 37: END expected
function RAROpenArchive; external; stdcall;
.............................................^
UnRAR.pas(148): Error 36: BEGIN expected
function RAROpenArchive; stdcall; external;
...................................^
AF>>>> программа не запускается, если юнит UnRAR
AF>>>> был скомпилирован до этого. Если поглядеть в код программы, в
AF>>>> ней вообще отсутствует упоминание об unrar.dll. Это глюк
AF>>>> компилятора? Или фича? Или я что-то не так делаю?
SR>>> Какую ошибку выводит?
AF>> RTE216 или вообще ошибку инициализации.
SR>>> unrar.dll не может отсутсвовать, он должен быть в importtable.
AF>> HЕТУ ЕГО ТАМ. Причем только если собирать второй раз, не
AF>> пересобирая UnRAR.pas.
SR> Hу тебе вроде тут ответили чего-то. Хотя мне проблема не понятна :(
Тут другая проблема появилась.. :)
04.12.2005 в 20:28:09 Alexey Fayans написал к Sp0Raw:
DZ>>> Это "фича" компилятора. Он не сохраняет в юнитах упоминание о
DZ>>> dll.
SR>> В чем глюк? Что-то я не понимаю сути проблемы :)
AF> Глюк в том, что в отлинкованном модуле, в котором прописаны функции
AF> dll как external 'dllname.dll', не сохраняется упоминание о dll,
AF> которой эти функции пренадлежат. И программа, собранная с таким
AF> юнитом, попросту неработоспособна.
Hе может быть. Регулярно так описываю и всё работает. Пример:
function Register_Card (CardType:Word; card_num:Word):Smallint;stdcall;
...
function Register_Card; external 'Pci-Dask.dll' name 'Register_Card';
А что за VP у тебя? Помнится, с build 243 и у меня были какие-то странности
с функциями из dll, а после перехода на build 274 все проблемы исчезли.
С уважением, Alexey.
...В действительности всё совсем не так, как на самом деле.
On 05 Dec 2005 12:02 you wrote me:
AF>> Глюк в том, что в отлинкованном модуле, в котором прописаны
AF>> функции dll как external 'dllname.dll', не сохраняется упоминание
AF>> о dll, которой эти функции пренадлежат. И программа, собранная с
AF>> таким юнитом, попросту неработоспособна.
AK> Hе может быть. Регулярно так описываю и всё работает. Пример:
Я тебе могу на мыло прислать юнит и программу, просто собери ее два раза с
ключом -m и посмотри, что из этого получится.
AK> function Register_Card (CardType:Word;
AK> card_num:Word):Smallint;stdcall;
AK> ...
AK> function Register_Card; external 'Pci-Dask.dll' name 'Register_Card';
AK> А что за VP у тебя? Помнится, с build 243 и у меня были какие-то
AK> странности с функциями из dll, а после перехода на build 274 все
AK> проблемы исчезли.
279.