Search code examples
pythonmacosdelphictypeslazarus

Lazarus library using ctypes in Python for OSX


I have a very small library in Lazarus and I'm unable to use it with ctypes on my Mac. I don't really understand what I'm doing incorrectly, and I was hoping someone can point me in the right direction.

This is the code that I have in Lazarus. When compiling on a Linux machine (Ubuntu VM), everything works fine. I can create a Linux .so file, and using ctypes, I can call into the shared library.

library project1;

{$mode delphi}{$H+}

{$IFDEF Darwin}
{$linkframework CoreFoundation}
{$linkframework Carbon}
{$ENDIF}

function SubStr(CString: PChar;FromPos,ToPos: Longint): PChar; cdecl;

var
  Length: Integer;

begin
  Length := StrLen(CString);
  SubStr := CString + Length;
  if (FromPos > 0) and (ToPos >= FromPos) then
  begin
    if Length >= FromPos then
      SubStr := CString + FromPos - 1;
    if Length > ToPos then
    CString[ToPos] := #0;
  end;
end;

exports
  SubStr;

end.

The Python code for this is below.

import ctypes

lib = ctypes.CDLL('./libproject1.so')


lib.SubStr.argtypes = (ctypes.c_char_p, ctypes.c_int64, ctypes.c_int64)
lib.SubStr.restype = ctypes.c_char_p

lib.SubStr('HelloWorld', 1, 5)
# The output is 'Hello' as expected

However, when I test the same thing on my Mac, I get the following error.

---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
<ipython-input-44-37971b70da86> in <module>()
      1 import ctypes
      2 
----> 3 ctypes.CDLL('./libproject1.dylib')

/Users/$USER/miniconda2/lib/python2.7/ctypes/__init__.pyc in __init__(self, name, mode, handle, use_errno, use_last_error)
    360 
    361         if handle is None:
--> 362             self._handle = _dlopen(self._name, mode)
    363         else:
    364             self._handle = handle

OSError: dlopen(./libproject1.dylib, 6): no suitable image found.  Did find:
    ./libproject1.dylib: mach-o, but wrong architecture

I've created a new project on the mac and tried the same thing to no avail.

On using lipo on this dylib, I get the following output.

$ lipo -info libproject1.dylib
Non-fat file: libproject1.dylib is architecture: i386

I believe this is what I'm supposed to get. Anyone have any suggestions on how to go about figuring this out?


Solution

  • Miniconda is evidently a 64-bit version of Python. Your library is 32 bits. (An architecture of i386 is 32-bit; you should see x86_64 for a 64-bit library.) Thus, Python correctly reports "wrong architecture."

    Recompile your library as a 64-bit binary and try again.