Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Export C++ function to python using ctypes: undefined symbol

Consider this file containing two similar functions:

#include <iostream>

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

int notmain()
{
  std::cout << "notmain\n";
}

I compiled this into a shared library:

g++ -shared -Wl,-soname,code -o code.so -fPIC code.cpp

I wish to call these from python, for main this works fine:

import ctypes
libc = ctypes.cdll.LoadLibrary("code.so")
libc.main()

Which prints main. However, notmain doesn't work:

import ctypes
libc = ctypes.cdll.LoadLibrary("code.so")
libc.notmain()

The output:

<ipython-input-63-d6bcf8b748de> in <module>()
----> 1 libc.notmain()

/usr/lib/python3.4/ctypes/__init__.py in __getattr__(self, name)
    362         if name.startswith('__') and name.endswith('__'):
    363             raise AttributeError(name)
--> 364         func = self.__getitem__(name)
    365         setattr(self, name, func)
    366         return func

/usr/lib/python3.4/ctypes/__init__.py in __getitem__(self, name_or_ordinal)
    367 
    368     def __getitem__(self, name_or_ordinal):
--> 369         func = self._FuncPtr((name_or_ordinal, self))
    370         if not isinstance(name_or_ordinal, int):
    371             func.__name__ = name_or_ordinal

I assume that main is 'exported' to the outside world (w.r.t. code.so) in a different way than notmain because main is a special case in the c++ specs. How can I 'export' notmain in the same way? Or: how can I fix the exception?

EDIT As suggested by @abdallahesam I added estern "C" to notmain, this did not change (or solve) the problem:

#include <iostream>

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

extern "C" {
  int notmain()
  {
std::cout << "notmain\n";
  }
}

CORRECTION

The suggestion did solve the problem, I just needed to restart the (i)python session. Apparently this matters :)

like image 670
Herbert Avatar asked Dec 20 '15 11:12

Herbert


People also ask

Why is ctypes used in Python?

ctypes is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap these libraries in pure Python.

How do you unload a DLL in Python?

You can then use dll_close(dll. _handle) to unload a library dll = ctypes. CDLL("your-library") . This list is taken from this file.

Does ctypes work with C++?

ctypes is the de facto standard library for interfacing with C/C++ from CPython, and it provides not only full access to the native C interface of most major operating systems (e.g., kernel32 on Windows, or libc on *nix), but also provides support for loading and interfacing with dynamic libraries, such as DLLs or ...


1 Answers

I think you should add extern "C" to your notmain function header to prevent c++ compiler from altering function name.

like image 84
abdallahesam Avatar answered Oct 23 '22 03:10

abdallahesam