I am trying to call a function from within a class which from what I understand, you just call as expected "object.class.function" is this correct, or am I doing something else wrong?
cLibrary.c
#include <stdio.h>
#include "clibrary.h"
void Clibrary::prompt()
{
printf("hello world\n");
}
cLibrary.h
class Clibrary
{
public:
Clibrary(){};
~Clibrary(){};
static void prompt();
};
Then build it
g -fPIC -shared -o clibrary.so cLibrary.c
Then test if it has the correct symbol
$ nm -gDC clibrary.so
w __cxa_finalize
w __gmon_start__
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
U puts
000000000000111a T Clibrary::prompt()
Then call it using CTypes in test.py.
#!/usr/bin/python3
import ctypes
libObject = ctypes.CDLL('./clibrary.so')
libObject.Clibrary.prompt()
Then try to run it
./test.py
Traceback (most recent call last):
File "./test.py", line 5, in <module>
libObject.Clibrary.prompt()
File "/usr/lib/python3.8/ctypes/__init__.py", line 386, in __getattr__
func = self.__getitem__(name)
File "/usr/lib/python3.8/ctypes/__init__.py", line 391, in __getitem__
func = self._FuncPtr((name_or_ordinal, self))
AttributeError: ./clibrary.so: undefined symbol: Clibrary
NO STACK OVERFLOW MODERATORS: it is not like Calling C function from python using ctypes because it is within a class.
CodePudding user response:
ctypes
understands C linkage and a C library normally needs to create extern "C"
wrapper functions. In this special case you can force ctypes
to load the name-decorated C symbol for the static method, but it isn't recommended.
Here's both demonstrated:
test.cpp
#include <stdio.h>
#ifdef _WIN32
# define API __declspec(dllexport) // Windows requires explicit export of functions.
#else
# define API
#endif
class API Clibrary // exported to see name decoration, but not needed
{
public:
Clibrary() {};
~Clibrary() {};
static void prompt() { printf("hello world\n"); }
};
// wrapper function with C linkage
extern "C" API void prompt() { Clibrary::prompt(); }
List of symbols exported from the DLL:
ordinal hint RVA name
1 0 00001020 ??0Clibrary@@QEAA@XZ
2 1 00001030 ??1Clibrary@@QEAA@XZ
3 2 00001040 ??4Clibrary@@QEAAAEAV0@AEBV0@@Z
4 3 00001050 ?prompt@Clibrary@@SAXXZ
5 4 00001000 prompt
test.py
import ctypes
libObject = ctypes.CDLL('./test')
# Hack but works. Decorated name is not standard and could
# be different using a different compiler.
other = getattr(libObject,'?prompt@Clibrary@@SAXXZ')
other()
libObject.prompt() # best and portable
Output:
hello world
hello world