title: Invalid ELF header when loading library from Python using ctypes.cdll.LoadLibrary
body: <p>I am just getting started with gcc on Linux.  I am following the tutorial <a href="http://www.network-theory.co.uk/docs/gccintro/gccintro_79.html" rel="nofollow">here</a>, except that I am using the g++ compiler.</p>
  
  <p>hello_fn.cpp</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include "hello.h"
  
  void 
  hello (const char * name)
  {
    printf ("Hello, %s!\n", name);
  }
  </code></pre>
  
  <p>bye_fn.cpp</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include "hello.h"
  
  void 
  bye (void)
  {
    printf ("Goodbye!\n");
  }
  </code></pre>
  
  <p>hello.h</p>
  
  <pre><code>void hello (const char * name);
  void bye (void);
  </code></pre>
  
  <p>I then run the following in the shell:</p>
  
  <pre><code>$ g++ -Wall -c hello_fn.cpp
  $ g++ -Wall -c bye_fn.cpp
  $ ar cr libhello.a hello_fn.o bye_fn.o
  </code></pre>
  
  <p>Then I try the following from python:</p>
  
  <pre><code>Python 2.7.1+ (r271:86832, Apr 11 2011, 18:05:24) 
  [GCC 4.5.2] on linux2
  Type "help", "copyright", "credits" or "license" for more information.
  &gt;&gt;&gt; import ctypes 
  &gt;&gt;&gt; test = ctypes.cdll.LoadLibrary(r'/home/oob/development/libtest/libhello.a')
  Traceback (most recent call last):
    File "&lt;stdin&gt;", line 1, in &lt;module&gt;
    File "/usr/lib/python2.7/ctypes/__init__.py", line 431, in LoadLibrary
      return self._dlltype(name)
    File "/usr/lib/python2.7/ctypes/__init__.py", line 353, in __init__
      self._handle = _dlopen(self._name, mode)
  OSError: /home/jeff/development/libtest/libhello.a: invalid ELF header
  </code></pre>
  
  <p>My idea was to write some functions in c++ and call them from Python.  Any ideas?</p>
  
  <p>UPDATE: I was able to get things "working".  Based on what Cat Plus Plus said, I may not go this direction for new code, but I was able to get this to work with a large legacy c++ library that I was porting from Windows to Linux.  We need a frontend to call some long running functions from this library, so I thought Python might be easiest.  The functions create a lot of output and only return an integer return code, so maybe I can avoid the "painful" stuff Cat Plus Plus was saying.  </p>
  
  <p>Here is what I did.</p>
  
  <p>Modified hello_fn.cpp</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include "hello.h"
  
  extern "C" int 
  hello (void)
  {
    return 16;
  }                                                                                
  </code></pre>
  
  <p>Modified by_fn.cpp</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include "hello.h"
  
  extern "C" void 
  bye (void)
  {
    printf ("Goodbye!\n");
  }
  </code></pre>
  
  <p>Modified hello.h</p>
  
  <pre><code>extern "C" int hello (void);
  extern "C" void bye (void);
  </code></pre>
  
  <p>buildscript.sh</p>
  
  <pre><code>#!/bin/bash
  
  rm *.o
  rm *.so
  
  g++ -fpic -g -c -Wall hello_fn.cpp
  g++ -fpic -g -c -Wall bye_fn.cpp
  #make a shared library, not a static library (thanks cat plus plus)
  g++ -shared -o libhello.so hello_fn.o bye_fn.o
  </code></pre>
  
  <p>test.py</p>
  
  <pre><code>#!/usr/bin/python
  
  import ctypes
  
  c = ctypes.cdll.LoadLibrary(r'/home/jeff/development/libtest/libhello.so')
  a = c.hello()
  print 'hello was ' + str(a)
  c.bye()
  </code></pre>
  
  <p>Try it in the terminal....</p>
  
  <pre><code>oob@ubuntu:~/development/libtest$ ./build_script.sh 
  oob@ubuntu:~/development/libtest$ python test.py 
  hello was 16
  Goodbye!
  </code></pre>
  
  <p>Our legacy library doesn't really use any windows-specific c++ stuff (thanks to the guy who wrote that code), so it has been a pretty easy port.  We had several functions that used extern "C" to expose functions.  For the port, I have made the following changes:</p>
  
  <pre><code>#ifdef LINUX
  #define __stdcall
  #endif
  #ifdef WINDOWS
  #define __stdcall __stdcall
  #endif
  </code></pre>
  
  <p>And for one of our functions, I can just leave it unchanged, for example:</p>
  
  <pre><code>extern "C" long __stdcall reform_proj {
      //do a bunch of stuff
      return 0;
  }
  </code></pre>