Home > OS >  Cannot call C class function in Python
Cannot call C class function in Python

Time:12-14

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.

CodePudding user response:

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.)

  • Related