Linux и shared library

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Linux и shared library

Сообщение Karpenko Yuri » 26.07.2007 22:21:14

Доброго времени суток!

Решил попробовать Free Pascal для разработки проекта.
И практически сразу столкнулся с проблемой, в точности похожей на эту, с той лишь разницей, что у меня не FreeBSD, а Linux (Ubuntu 7.04).

Под Windows работают оба варианта (и со статической линковкой, и с динамической), под Linux - только со статической (если дать ссылку на библиотеку в /usr/lib; если не давать - тоже не работает, но это понятно - в мануале чёрным по-английски написано).

Привожу код:

Библиотека -
Код: Выделить всё
{$MODE OBJFPC}
library testlib;

procedure testproc; stdcall; export;
begin
  WriteLn('TestProc called');
end;

exports
  testproc;

end.

Программа (динамическая линковка) -
Код: Выделить всё
{$MODE OBJFPC}
program testprog;

uses
  sysutils, dynlibs;

const
  Name_TestLib  = 'testlib';
  Name_TestProc = 'testproc';
 

procedure Debug(const aFn, aStr: AnsiString);
begin
   WriteLn(TimeToStr(Now) + ' - ' + aFn + ': ' + aStr);
end;

procedure UnLoadLib(var LibHandle: TLibHandle);
begin
  if LibHandle<>NilHandle then
  begin
    Debug('UnLoadLibrary', IntToStr(LibHandle));
    UnLoadLibrary(LibHandle);
  end;

  LibHandle := NilHandle;
end;

function GetLibProcAddr(const LibName, ProcName: AnsiString; var H: TLibHandle): Pointer;
begin
  Result := nil;

  if H=NilHandle then
  begin
    Debug('LoadLibrary', LibName);
    H := LoadLibrary(LibName);
    if H<>NilHandle
    then Debug('LoadLibrary', LibName+'; Handle='+IntToStr(H));
  end;

  if H=NilHandle
  then Debug('LoadLibrary', LibName+' failed!')
  else
  begin
    Debug('GetProcedureAddress', LibName+'.'+ProcName);

    Result := GetProcedureAddress(H, ProcName);

    if not(Assigned(Result)) then
    begin
      Debug('GetProcedureAddress', LibName+'.'+ProcName+' failed!');
      UnLoadLib(H);
    end;
  end;
end;

type
  TTestProc = procedure; stdcall;
var
  Handle_LibTest : TLibHandle;
  TestProc       : TTestProc;
begin
  Handle_LibTest := NilHandle;
  try
    TestProc := TTestProc(GetLibProcAddr(Name_TestLib, Name_TestProc, Handle_LibTest));
    if Assigned(TestProc)
    then TestProc;
  finally
    UnLoadLib(Handle_LibTest);
  end;
end.

Программа (статическая линковка) -
Код: Выделить всё
{$MODE OBJFPC}
program testprog1;

procedure testproc; stdcall; external 'testlib';

begin
  testproc;
end.


Есть у кого какие соображения?
Karpenko Yuri
незнакомец
 
Сообщения: 2
Зарегистрирован: 26.07.2007 20:41:45
Откуда: Москва

Сообщение Karpenko Yuri » 27.07.2007 11:50:39

Опытным путём установил, что для Linux нужно самому указывать префикс ('lib') и расширение ('.so') библиотеки.

Код: Выделить всё
function GetLibProcAddr(const LibName, ProcName: AnsiString; var H: TLibHandle): Pointer;
begin
  Result := nil;

  if H=NilHandle then
  begin
    Debug('LoadLibrary', LibName);

    {$IFDEF Windows}
    H := LoadLibrary(ALibName);
    {$ELSE}
    H := LoadLibrary('lib'+ALibName+'.so');
    {$ENDIF}

    if H<>NilHandle
    then Debug('LoadLibrary', LibName+'; Handle='+IntToStr(H));
  end;

  if H=NilHandle
  then Debug('LoadLibrary', LibName+' failed!')
  else
  begin
    Debug('GetProcedureAddress', LibName+'.'+ProcName);

    Result := GetProcedureAddress(H, ProcName);

    if not(Assigned(Result)) then
    begin
      Debug('GetProcedureAddress', LibName+'.'+ProcName+' failed!');
      UnLoadLib(H);
    end;
  end;
end;


В связи с этим возникают другие вопросы: почему этим не занимается dynlibs? Это ошибка или фича? Как с этим будет обстоять в будущих версиях FP (я проверял на 2.0.4)?
Karpenko Yuri
незнакомец
 
Сообщения: 2
Зарегистрирован: 26.07.2007 20:41:45
Откуда: Москва

Сообщение Sergei I. Gorelkin » 27.07.2007 12:50:19

Баг или фича - вопрос философский. Windows и Linux ведут себя по-разному, а кроме них есть еще всякие полуоси и т.д. Сейчас dynlibs просто не содержит в себе никакого "интеллекта" и поэтому ведет себя так же, как и операционка, на которой работает.
В более поздних версиях добавили ф-цию SafeLoadLibrary, но больше ничего не меняли.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1406
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0

Рейтинг@Mail.ru