2

C++ code:

#include <iostream>
class DemoClass{
    private:
        int a, b;
    public:
        DemoClass(int v1, int v2){
            a = v1;
            b = v2;
        }
        void DemoFunction(){
            std::cout << "Hello C++!" << std::endl;
            std::cout << "output: a = " << a << ", b = " << b << std::endl;
        }
};

extern "C" {
    DemoClass* DemoCpp(int v1, int v2){
        return new DemoClass(v1, v2);
    }
    void DemoCppFunction(DemoClass* demo){
        demo->DemoFunction();
    }
}

compile c++ via g++ test.cpp -shared -fPIC -o test.so

Python script:

from ctypes import cdll
lib = cdll.LoadLibrary('./test.so')

class CppClass():
    def __init__(self, v1: int, v2: int):
        self.obj = lib.DemoCpp(v1, v2)

    def demoFunction(self):
        lib.DemoCppFunction(self.obj)

f = CppClass(2, 3)
f.demoFunction()

Here is what I get:

Hello C++!
Segmentation fault

I am pretty sure the parameters are passed to C++ class. I just want to know a way to call the function in a C++ class.

2
  • Use pybind11 perhaps? Commented Dec 14, 2022 at 5:47
  • Have you tried to debug? Commented Dec 14, 2022 at 5:51

1 Answer 1

4

Python's ctypes doesn't do a lot of heavy lifting for you. It assumes that the argument and return types for cdll functions are all int until proven otherwise. So while your C++ code knows it's returning a DemoClass*, Python is truncating that to an integer, and on modern 64-bit systems pointers don't fit into plain integers.

Since you don't plan to use this pointer in Python for anything other than calling DLL functions, we don't have to reconstruct our structure on the Python side. Instead, we can use void*, the type of pointers to arbitrary data. In Python, we call this type c_void_p.

At the top of your program, just after loading the DLL, consider

lib.DemoCpp.argtypes = (c_int, c_int)
lib.DemoCpp.restype = c_void_p
lib.DemoCppFunction.argtypes = (c_void_p,)
lib.DemoCppFunction.restype = None

(Note: We can get away without lines 1 and 4 here, since Python will happily assume integer argument types, and our DemoCppFunction doesn't return anything so we don't try to use its return value. But for consistency, we may as well be explicit.)

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your reply. It works well!!!!! What about I want to use DemoClass* and DemoCppFunction will return something? like this: DemoCppFunction will modify the value of a and return. ``` DemoClass* DemoCppFunction(DemoClass* demo){ demo->DemoFunction(); demo->a = 100; return demo; } ``` And I want to get the modified instance in python ``` newDemo = f.demoFunction() print(newDemo.a) # I know this does not work. ```
Anywhere that you return an (opaque) pointer to struct in C++, set the restype to c_void_p in Python.

Your Answer

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.