Ctypes not finding symbols in shared library created using CMake

10,166

Interesting, I usually use numpy.ctypes since I constantly have to deal with large data sets, and never had any issues but I think I know whats going on here, it's that the names are being mangled by the g++ compiler, I made it work this way:

Makefile:

g++ -Wall -fPIC -O2 -c Utils.cpp
g++ -shared -Wl -o libUTILS.so Utils.o

Utils.cpp

extern "C" double addTwoNumber(double x, double y)
{
    return x + y;
}

test.py

import os
import ctypes as c

libUTILS = c.cdll.LoadLibrary('libUTILS.so')

prototype = c.CFUNCTYPE(    
    c.c_double,                
    c.c_double,                
    c.c_double                
)
addTwoNumber = prototype(('addTwoNumber', libUTILS))

res = addTwoNumber(c.c_double(2.3), c.c_double(3.5) )
print res

output:

$ python test.py
5.8

note the extern keyword this makes sure the compiler doesn't mangle the name, you have to do some extra stuff when under windows, I did find http://wolfprojects.altervista.org/dllforpyinc.php which was kind of interesting.

I hope this helps.

my machine:

$ g++ --version
i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3) Copyright (C) 2007 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ uname -a
Darwin MacBookPro 10.8.0 Darwin Kernel Version 10.8.0: Tue Jun 7 16:33:36 PDT 2011; root:xnu-1504.15.3~1/RELEASE_I386 i386

Share:
10,166
Maverick
Author by

Maverick

Updated on June 05, 2022

Comments

  • Maverick
    Maverick almost 2 years

    My CMake setting to create a shared lib in linux is something like

    SET (CMAKE_CXX_FLAGS "-fPIC")
    
    SET (LIB_UTILS_SRC
        Utils.cpp
    )
    
    ADD_LIBRARY (UTILS SHARED
        ${LIB_UTILS_SRC}
    )
    

    Source Utils.cpp

    double addTwoNumber(double x, double y)
    {
        return x + y;
    }
    

    When trying to access 'addTwoNumber' function using CTypes like

    import os
    import ctypes as c
    
    libPath = '/home/AP/workspace/LearningCPP/lib/libUTILS.so'
    libUTILS = c.cdll.LoadLibrary(libPath)
    
    prototype = c.CFUNCTYPE(    
        c.c_double,                
        c.c_double,                
        c.c_double                
    )
    addTwoNumber = prototype(('addTwoNumber', libUTILS))
    
    res = addTwoNumber(c.c_double(2.3), c.c_double(3.5) )
    

    I am getting some message like.

    AttributeError: /home/AP/workspace/LearningCPP/lib/libUTILS.so:
    undefined symbol: addTwoNumber
    

    I checked the libUTILS.so using the "nm --demangle libUTILS.so" command and it clearly shows the 'addTwoNumber' symbol in it.

    Why am I still getting the "undefined symbol" message from python ? I am guessing there must be some compiler flags to be set so that symbols are mangle properly. Any suggestion would be appreciated !