Question

I'm trying to use some C++ method in my python code and I'm using ctypes library. I have wrote a simple C++ code using a simple main with no arguments and another simple method named printArgs which takes an argument of type char *. I also have wrote a simple python code to import these two methods. I made two linked libraries(one .so and one .a because I'm using Debian) with this command:

g++ -o hello.so -shared -fPIC hello.cpp 

And then used export LD_LIBRARY_PATH=/the/path/to/the/linked/libraries/directory.

There is no problem in getting the main method, bu when I'm trying to get printArgs I get AttributeError. Here's the C++ code:

#include <iostream>
using namespace std;

int printArgs(char * args_array){
    for (int i = 0; i < 5; i++){
        cout<<i<<"- "<<args_array[i]<<"\n";
    }
    return 0;
}

int main(){
    cout<<"Hello\n";
    return 0;
}

Here's the Python code:

from ctypes import *
helloInCPP_lib = cdll.LoadLibrary("hello.a")
print helloInCPP_lib
helloInCPPMain = helloInCPP_lib.main
print helloInCPPMain
helloInCPPPrint = helloInCPP_lib.printArgs
print helloInCPPPrint

I get this output:

<CDLL 'hello.a', handle 9c45488 at b73d1e6c>
<_FuncPtr object at 0xb73e67e4>
Traceback (most recent call last):
    File "testHelloInCPP.py", line 9, in <module>
        helloInCPPPrint = helloInCPP_lib.printArgs(None)
    File "/usr/lib/python2.6/ctypes/__init__.py", line 366, in __getattr__
        func = self.__getitem__(name)
    File "/usr/lib/python2.6/ctypes/__init__.py", line 371, in __getitem__
        func = self._FuncPtr((name_or_ordinal, self))
AttributeError: /etc/linked_libraries/hello.a: undefined symbol: printArgs

I also tried cdll.LoadLibrary("hello.so") and/or helloInCPPPrint = helloInCPP_lib.printArgs(None); got the same error in both conditions. Any idea?

I'm using Debian 32 bit on a VMWare Workstation and Python 2.6.

Was it helpful?

Solution

Declare the printArgs using extern "C":

#include <iostream>
using namespace std;

extern "C" {
    int printArgs(char * args_array);
}

int printArgs(char * args_array){
    for (int i = 0; i < 5; i++){
        cout<<i<<"- "<<args_array[i]<<"\n";
    }
}

int main(){
    cout<<"Hello\n";
}

BTW, you should pass a string (c_char_p), not None:

...
helloInCPPPrint = helloInCPP_lib.printArgs
helloInCPPPrint.argtypes = [c_char_p]
print helloInCPPPrint("ABCDE")

About argtypes, see Specifying the required argument types (function prototypes).

OTHER TIPS

I tired compiling the solution by @falsetru using

g++ -O3 -shared -std=c++11 -fPIC code.cpp -o lib.so

but could not without this small modification to code.c, according to the link provided in their answer extern "C":

#include <iostream>
using namespace std;

extern "C" int printArgs(char * args_array){
    for (int i = 0; i < 5; i++){
        cout<<i<<"- "<<args_array[i]<<"\n";
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top