2

I am trying to write a c routine to speed up a python script.

In order to route prove my method I first wrote a short test c function and compiled it into a library: the code for the test function is:

void cttest(void);
#include <stdio.h>

void cttest()
{
    printf("This is the shared module|n");
    return;
}

I saved this code into a file 'ct_test.cc'.

I then compiled this code as follows:

g++ -shared -fPIC -o /home/paula/libs/libcttest.so ct_test.cc

which gave no errors or warnings.

I then loaded ipython and typed the following:

import ctypes as ct

test=ct.CDLL("/home/paula/libs/libcttest.so")

if I now try to access the function (by typing 'test.' and then hitting tab) nothing happens.

If I do this:

What am I doing wrong?

Oh, just in case it makes any difference:

OS: xubuntu 14.10 Python: 2.7.8 ipython: 2.3.0 g++ : 4.9.1

Paula Thomas
  • 1,152
  • 1
  • 8
  • 13
  • The syntax used at https://docs.python.org/2/library/ctypes.html#loading-dynamic-link-libraries is different. You could try their suggestion. – R Sahu Jan 10 '15 at 05:56
  • Thank you very much for taking the time to comment and for your suggestion. I have now tried the 'cdll.LoadLibrary' syntax and the result is the same. – Paula Thomas Jan 10 '15 at 06:26
  • Type `test.cttest()`. Don't assume tab-completion works. – Mark Tolonen Jan 10 '15 at 07:52
  • 1
    Using C++, the name stored in the library will differ from just 'cttest' (there's name mangling). To prevent this, add `extern "C" ` just before your first line to inform g++ that the C-style name should be stored instead. – brm Jan 10 '15 at 09:50
  • Thankyou to Mark Tolonen and brm for the replies. Mark, I tried both, neither worked. I will try brm's suggestion next. Thakyou both once again. – Paula Thomas Jan 10 '15 at 10:01
  • 1
    I am delighted to tell you all that brm is right! Thankyou all for your help – Paula Thomas Jan 10 '15 at 10:42
  • eryksun, Thankyou for your comment. I would merely point out that, as R Sahu says, the documentation, in its examples, uses cdll.LoadLibrary. I must confess I find the reasons for this incomprehensible for precisely the reasons you state. I do however feel obliged to point out that not all of us use Windows so "kernel32" is not known to some of us. – Paula Thomas Jan 10 '15 at 19:43
  • Sorry, using kernel32 was a bad example given this is tagged Linux. The `__getattr__` usage such as `cdll.msvcrt` is only applicable to Windows. On Linux demonstrating the caching problem requires using `__getitem__`, e.g. `cdll['/home/paula/libs/libcttest.so']`. This can lead to prototype collisions across modules. Using `cdll.LoadLibrary` calls `CDLL` without caching, but you may as well call `CDLL` directly. – Eryk Sun Jan 10 '15 at 23:24
  • Well I didn't expand the comments before answering so missed that it was solved. – Flexo Jan 13 '15 at 10:11

1 Answers1

3

You have two problems:

  1. Firstly as has already been noted tab auto-complete won't work for ctypes until a function has been used for the first time. (It wouldn't be impossible to make it work on most platforms, but it would add a fair overhead to loading the library I suspect).
  2. You've written C and you're trying to call it like C, but you used a C++ compiler so you have a name mangling problem.

The solution to the first problem is trivial - use the full name and don't rely on auto-completion. There are at least 3 solutions to the second, I've written them here from best to worst:

  1. Use a C compiler instead of C++ compiler. (gcc instead of g++).
  2. Use extern "C" to force the C++ compiler to not mangle the function name:

    extern "C" void cttest(void);
    
    extern "C" 
    {
        void cttest()
        {
            printf("This is the shared module\n");
            return;
        }
    }
    
  3. Use the mangled C++ name in Python, in this case it would be _Z6cttestv

To prove that this works I tried it out on Ubuntu 14.04:

gcc -shared -fPIC -o libcttest.so test.c

And using it in ipython:

ipython
Python 2.7.6 (default, Mar 22 2014, 22:59:38) 
Type "copyright", "credits" or "license" for more information.

IPython 1.2.1 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: import ctypes as ct

In [2]: test=ct.CDLL('./libcttest.so')

In [3]: test.cttest()
This is the shared module
Out[3]: 26
Community
  • 1
  • 1
Flexo
  • 87,323
  • 22
  • 191
  • 272