c++pythonctypesundefined-symbol

Attribute error while using methods from linked libraries in python


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.


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).