48
[me@hostname python]$ cat hello_world.cc
#include <string>
#include <Python.h>
#include <boost/python.hpp>

namespace {
  std::string greet() { return "Helloworld"; }
}

using namespace boost::python;

BOOST_PYTHON_MODULE(hello_world)
{
  def("greet",greet);
}

[me@hostnmae python]$ g++ -c -fPIC hello_world.cc -I/path/to/boost/headers -I/path/to/python/headers -o hello_world.o
[me@hostname python]$ g++ -shared -Wl,-soname,libhello_world.so -o libhello_world.so  hello_world.o
[me@hostname python]$ python
Python 2.7.1 (r271:86832, Jan 10 2011, 09:46:57)
[GCC 3.4.5 20051201 (Red Hat 3.4.5-2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path.append('.')
>>> import hello_world
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named hello_world
>>>

I created the .so file as shown above but I'm not able to import inside python. what am I missing?

balki
  • 26,394
  • 30
  • 105
  • 151

2 Answers2

28

take that 'hello_world.so' file and and make new python file (in the same dir) named as 'hello_world.py'. Put the below code in it.. .

def __bootstrap__():
   global __bootstrap__, __loader__, __file__
   import sys, pkg_resources, imp
   __file__ = pkg_resources.resource_filename(__name__,'hello_world.so')
   __loader__ = None; del __bootstrap__, __loader__
   imp.load_dynamic(__name__,__file__)
__bootstrap__()

now you can import this hello_world as:

>>> import hello_world
namit
  • 6,780
  • 4
  • 35
  • 41
  • 5
    Should "\__bootstrap__" be renamed to, say "\_bootstrap"? I spent a lot of time trying to find the documentation for it, thinking it was a special reserved word, but I couldn't find anything. From https://www.python.org/dev/peps/pep-0008/#naming-conventions: \__double_leading_and_trailing_underscore__ : "magic" objects or attributes that live in user-controlled namespaces. E.g. \__init__ , \__import__ or \__file__ . Never invent such names; only use them as documented. – Jay West Aug 11 '15 at 00:38
  • 4
    we can copy but can u add some detail about info.How does it work. – user765443 Aug 04 '17 at 07:39
  • I tried this with module readline. I happen to have a python version #1 (2.7.12) installed with apt-get, which has readline, and another version #2 (2.7.11), simply expanded, which does not. So I added a readline.py in one of the directories in sys.path for version #2, and a symlink in the same dir to /usr/lib/python2.7/lib-dynload/readline.x86_64-linux-gnu.so from version #1. I still get the error. – sancho.s ReinstateMonicaCellio Mar 08 '18 at 05:24
  • is this the only solution? I don't see this any Cython documentation so it feels like a workaround. – mLstudent33 Oct 31 '19 at 02:00
26

It must be called hello_world.so, not libhello_world.so.

Cat Plus Plus
  • 125,936
  • 27
  • 200
  • 224
  • 4
    thanks. Now I get `ImportError: ./hello_world.so: undefined symbol: _ZNK12boost_1_47_06python7objects21py_function_impl_base9max_arityEv` – balki Jun 10 '12 at 11:38
  • 2
    @balki: You didn't link with Boost.Python. – Cat Plus Plus Jun 10 '12 at 11:39
  • I linked against boost_python, Now I get `ImportError: libboost_python: cannot open shared object file: No such file or directory`. If I export `LD_LIBRARY_PATH=/path/to/boost_python_lib`, it works fine. How do I specify in cmdline? – balki Jun 10 '12 at 12:16
  • 7
    `LD_LIBRARY_PATH=/path/to/boost_python_lib python` would be straightforward. I'd suggest you symlink `boost_python_lib` to `/usr/local/lib` if you can, then you get it hassle-free. You can also hardcode the path in the `.so` file by passing `-Wl,-rpath=/path/to/boost_python_lib` to the compiler (which is actually processed by the linker). – eudoxos Jun 16 '12 at 12:09