title: How to include a shared C library in a Python package
body: <p>I have a project depending on a shared library. To make it clear from the beginning: the shared library is a pure C library and not a Python library. For reasons of simplicity I created a small demo project called <em>pkgtest</em> which I will refer to. </p>
  
  <p>So what needs to be done is: Run a Makefile to compile the library and place the compiled shared library (called <code>libhello.so</code> here) file somewhere it can be accessed from within the depending Python package. </p>
  
  <p>My best guess so far was to run the makefile as a preinstallation routine, copy the <code>libhello.so</code> file in the packages directory and add it to the <code>package_data</code> parameter of the setup script. When installed the shared library then gets placed in the <code>site-packages/pkgtest/</code> directory and can be accessed from the module.</p>
  
  <p>The package directory is structure is as simple as this:</p>
  
  <pre><code>pkgtest/
    src/
       libhello.c
       libhello.h
       Makefile
    pkgtest/
      __init__.py
      hello.py
    setup.py
  </code></pre>
  
  <p>My setup.py looks like this:</p>
  
  <p><em>setup.py</em></p>
  
  <pre><code>import subprocess
  from setuptools import setup
  from distutils.command.install import install as _install
  
  
  class install(_install):
      def run(self):
          subprocess.call(['make', 'clean', '-C', 'src'])
          subprocess.call(['make', '-C', 'src'])
          _install.run(self)
  
  
  setup(
      name='pkgtest',
      version='0.0.1',
      author='stefan',
      packages=['pkgtest'],
      package_data={'pkgtest': ['libhello.so']},
      cmdclass={'install': install},
  )
  </code></pre>
  
  <p>The Makefile actually builds the library and copies it into the directory of my python package.</p>
  
  <p><em>src/Makefile</em></p>
  
  <pre><code>all: libhello.so
  
  libhello.o: libhello.c
          gcc  -fPIC -Wall -g -c libhello.c
  
  libhello.so: libhello.o
          gcc -shared -fPIC -o libhello.so libhello.o
          cp libhello.so ../pkgtest/libhello.so
  
  clean:
          rm -f *.o *.so
  </code></pre>
  
  <p>So all <code>hello.py</code> is actually doing is load the library and call the <code>hello</code> function that prints some text. But for completeness I will show the code here:</p>
  
  <p><em>pkgtest/hello.py</em></p>
  
  <pre><code>import os
  import ctypes
  
  basedir = os.path.abspath(os.path.dirname(__file__))
  libpath = os.path.join(basedir, 'libhello.so')
  
  dll = ctypes.CDLL(libpath)
  
  def say_hello():
      dll.hello()
  </code></pre>
  
  <p>So this actually works but what I don't like about this approach is that the shared library lives in the directory of the Python package. I figure it would be better to put it in some sort of central library directory such as <em>/usr/lib/</em>. But for this one would need root privileges on installation. Has somebody got some experience with this kind of problem and would like to share a solution or helpful idea. Would be great.</p>