2

I have a closed-source x86_64 library that I want to access from Python on Linux.

I usually use ctypes for this.

But this library is supplied as an archive (*.a) file. I cannot relink the library into a dynamic *.so because it was compiled without the -fPIC option. ctypes needs the *.so dll.

Besides complaining to the packagers of this library, is there anything else I can do to get it into an *.so? Maybe writing wrapper functions somehow?

Edit:

Trying the answer in https://stackoverflow.com/a/2657390/4323:

gcc -shared -o closed_lib.so -Wl,--whole-archive -fPIC closed_lib.a -Wl,--no-whole-archive
/usr/bin/ld: closed_lib.a(myFFT.o): relocation R_X86_64_32S against `.bss' can not be used when making a shared object; recompile with -fPIC
closed_lib.a(myFFT.o): error adding symbols: Bad value
collect2: error: ld returned 1 exit status
make: *** [closed_lib.so] Error 1
Community
  • 1
  • 1
markrages
  • 334
  • 3
  • 14

1 Answers1

0

I made it work for a basic case, but it seems you discovered the same solution around the same time yet it didn't work for you. I will describe what I did anyway.

First, make a file static.c containing some C code (skip this if you have a static library already built):

int foo(int x) {
  return x * 2;
}

Make a static library:

gcc -g -o static.o -c static.c
ar -rv libstatic.a static.o

Now we have our position-dependent static library. Let's make a shared library!

gcc -g -shared -o libshared.so -Wl,--whole-archive -L. -lstatic -Wl,--no-whole-archive

And finally, test it using Python:

import ctypes
print ctypes.cdll.LoadLibrary('./libshared.so').foo(42)

This gives the expected 84.

I borrowed the approach from another answer, here: https://stackoverflow.com/a/10963770/4323


According to this: https://stackoverflow.com/a/19768349/4323 it may not be possible to do what you're trying to do. Maybe you really do need to rebuild your static library. Or maybe you can edit out the symbols that are causing you problems if you don't need those particular symbols? Do you have a list of symbols you really need?


If none of the above is helpful, a very different approach would be to create an executable program linked against your static library, and do something like RPC to run code in that process as a service.


Old answer, seems to only apply to Solaris:

From here: Linking a shared library against a static library: must the static library be compiled differently than if an application were linking it? it seems you need to add the -mimpure-text option when creating a shared library from a non-PIC static one.

Community
  • 1
  • 1
John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • 1
    According to "man gcc", -mimpure-text is only supported on Solaris 2. – markrages Oct 23 '14 at 07:18
  • @markrages: right you are. I've majorly revamped my answer now. You might be left with less-elegant options, but there are a few things to consider above. – John Zwinck Oct 23 '14 at 08:40