Alexey-T / Python-for-Lazarus

Fork of Python4Delphi for Lazarus, supports Windows/Linux/macOS/*BSD/Solaris
MIT License
127 stars 42 forks source link

Import(Py_DebugFlag) fails on MacOS #27

Closed pyscripter closed 3 years ago

pyscripter commented 3 years ago

This is a question about P4D.

P4D fails with fpc and MacOS, while your fork works. Please see https://en.delphipraxis.net/topic/4131-installingexecuting-python4delphi-app-on-macos-lazarus-could-not-map-symbol-p%EF%BB%BFy_debugflag%EF%BB%BF%EF%BB%BF%EF%BB%BF

I compared the source code and could not see any significant difference in Import and MapDLL. Any clues why P4D fails and P4L works?

Thanks!

Alexey-T commented 3 years ago

maybe different LoadLibrary/GetProcAddress code. P4L uses (inside FPC) CurrentDLM (dynamic load manager). i cannot find the place in FPC, because work PC has not MacOS support installed

pyscripter commented 3 years ago

P4D

uses
  Types,
{$IFDEF MSWINDOWS}
{$ELSE}
{$IFDEF FPC}
  Dl,
  DynLibs,
{$ELSE}
...
{$ENDIF}
...
{$ENDIF}
procedure TDynamicDll.DoOpenDll(const aDllName : string);
begin
  if not IsHandleValid then
  begin
    FDllName := aDllName;
    {$IFDEF MSWINDOWS}
    ...
    {$ELSE}
    //Linux: need here RTLD_GLOBAL, so Python can do "import ctypes"
    FDLLHandle := THandle(dlopen(PAnsiChar(AnsiString(GetDllPath+DllName)),
      RTLD_LAZY+RTLD_GLOBAL));
    {$ENDIF}
  end;
end;

function TDynamicDll.Import(const funcname: AnsiString; canFail : Boolean = True): Pointer;
var
  E : EDllImportError;
  {$IF not Defined(FPC) and not Defined(MSWINDOWS)}
  S : string;
  {$IFEND}
begin
  {$IF Defined(FPC) or Defined(MSWINDOWS)}
  Result := GetProcAddress( FDLLHandle, PAnsiChar(funcname) );
  {$ELSE}
  ...
  {$IFEND}
  if (Result = nil) and canFail then begin
  ...
  end;
end;

P4L uses

{$IFDEF windows}
{$ELSE}
  Types,
  Dl,
  DynLibs,
  Forms, //for Application.Terminate
{$ENDIF}

procedure TDynamicDll.DoOpenDll(const aDllName : String);
var
  S: String;
begin
  if not IsHandleValid then
  begin
    FDllName := aDllName;
    S := GetDllPath+DllName;

    {$ifdef windows}
    FDLLHandle := Windows.LoadLibrary(PChar(S));
    {$else}
    //Linux: need here RTLD_GLOBAL, so Python can do "import ctypes"
    FDLLHandle := PtrInt(dlopen(PAnsiChar(S), RTLD_LAZY+RTLD_GLOBAL));
    {$endif}
  end;
end;

function TDynamicDll.Import(const funcname: AnsiString; canFail : Boolean = True): Pointer;
var
  E : EDllImportError;
begin
  Result := GetProcAddress( FDLLHandle, PChar(funcname) );
  if (Result = nil) and canFail then begin
    E := EDllImportError.CreateFmt('Error: could not find symbol "%s"', [funcname]); //AT
    //E.ErrorCode := GetLastError;
    E.WrongFunc := funcname;
    raise E;
  end;
end;

Look the same to me.

Alexey-T commented 3 years ago

yes, look the same. I don't know...