Posted on 13-03-2013
Filed Under (Technology) by bigbang

If you want to invoke C/C++ third-party library ( third-party libraries are your libraries at the most time ), you just need a script to attach them. At this time, we can use Python ctypes to do this dirty job.

The theme Calling C/C++ from python on StackOverflow has introduced the basic usage of ctypes. The key points are:

  1. If you try to use C library, just load this library and use it.
  2. If you try to use C++ library, you should use keyword extern to wrapper C++ class into functions for C. That means we should put C++ class into C functions, and use keyword extern for statement.

In above two ways, if you get the way to use ctypes to invoke C++ library, then you also get the way to use ctypes to invoke C library. Let’s talk about how to invoke C++ library in details.

For example, there is a C++ class Foo:

#include <iostream>

class Foo{
    public:
        void bar(){
            std::cout << "Hello" << std::endl;
        }
};

Then we wrapper out following C style interfaces:

extern "C" {
    Foo* Foo_new(){ return new Foo(); }
    void Foo_bar(Foo* foo){ foo->bar(); }
}

We compile the code into library:

g++ -c -fPIC foo.cpp -o foo.o
g++ -shared -Wl,-soname,libfoo.so -o libfoo.so  foo.o

, then we can use Python to invoke this class. You can put the interfaces into a Python class or use them directly:

from ctypes import cdll
lib = cdll.LoadLibrary('./libfoo.so')

class Foo(object):
    def __init__(self):
        self.obj = lib.Foo_new()

    def bar(self):
        lib.Foo_bar(self.obj)

Everything is OK now. We can invoke this Python class like this:

f = Foo()
f.bar() #and you will see "Hello" on the screen

Under Windows, the process is the same if you try to use Python ctypes, but just need to pay attention to following two points:

  1. When start to link to C/C++ library, it is the best idea to use absolute path to load library.

    When I run above code under Windows, I got following error:

    $ python Linkcpp.py
    Traceback (most recent call last):
      File "Linkcpp.py", line 2, in <module>
        lib = cdll.LoadLibrary('./LinkExample')
      File "C:\Python27\lib\ctypes\__init__.py", line 431, in LoadLibrary
        return self._dlltype(name)
      File "C:\Python27\lib\ctypes\__init__.py", line 353, in __init__
        self._handle = _dlopen(self._name, mode)
    WindowsError: [Error 126]
    

    The reason is that I use following code to load library:

    from ctypes import cdll
    lib = cdll.LoadLibrary('./LinkExample')
    

    We can eliminate this error by changing ./LinkExample into E:/PythonCode/LinkCpp/LinkExample which is library’s absolute path under Windows. We can also use LinkExample if the library is under the same folder as the Python script.

    So, to save the debugging time, it is the best way to do it by using absolute path to load library.

    If you get WindowsError: [Error 126] message, the reason is nothing but two

    • Your DLL is not being located.
    • Your DLL depends on other DLLs that cannot be found.

    PS: The dynamic libraries under Windows has two lib & dll files. In this case, we can just use the name of the library.

  2. If the library is written by C++, then we should use extern to wrapper it.

    In the function stated by extern, we can also use the keyword belongs to C++ which is not in C. For example, we can describe our function like this:

    extern int linkExample(const int index, const char* name);
    

    Python ctypes can run it!

    The method of keyword extern in C++ is complicated. Here we just need to state a function to invoke by C, so we can use keyword const in it.

© 2013, The Big Bang on Reading Busy. All rights reserved.
On republishing this post you must provide link to the original post.

Post a Comment
Name:
Email:
Website:
Comments: