1

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.

asked Jul 6, 2022 at 0:43
1
  • It's "C" types. It can't call functions within a C++ class. It understands C functions and types. Commented Jul 6, 2022 at 1:28

1 Answer 1

3

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
answered Jul 6, 2022 at 1:49
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.