Export C++ function to python using ctypes: undefined symbol
Question:
Consider this file containing two similar functions:
#include <iostream>
int main()
{
std::cout << "mainn";
}
int notmain()
{
std::cout << "notmainn";
}
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 << "mainn";
}
extern "C" {
int notmain()
{
std::cout << "notmainn";
}
}
CORRECTION
The suggestion did solve the problem, I just needed to restart the (i)python session. Apparently this matters 🙂
Answers:
I think you should add extern “C” to your notmain function header to prevent c++ compiler from altering function name.
Another possible solution is to link all libraries dynamically to the one library you want to open by ctypes.
Consider this file containing two similar functions:
#include <iostream>
int main()
{
std::cout << "mainn";
}
int notmain()
{
std::cout << "notmainn";
}
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 << "mainn";
}
extern "C" {
int notmain()
{
std::cout << "notmainn";
}
}
CORRECTION
The suggestion did solve the problem, I just needed to restart the (i)python session. Apparently this matters 🙂
I think you should add extern “C” to your notmain function header to prevent c++ compiler from altering function name.
Another possible solution is to link all libraries dynamically to the one library you want to open by ctypes.