无法在Python中调用C++类函数

uinbv5nw  于 2022-12-15  发布在  Python
关注(0)|答案(1)|浏览(196)

C++代码:

#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();
    }
}

通过g++ test.cpp -shared -fPIC -o test.so编译c++
Python脚本:

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

这是我得到的:

Hello C++!
Segmentation fault

我很确定参数传递给了C类。我只是想知道在C类中调用函数的方法。

dfuffjeb

dfuffjeb1#

Python的ctypes并没有为你做太多繁重的工作,它假设cdll函数的参数和返回类型都是int,除非证明不是这样,所以当你的C++代码知道它返回的是一个DemoClass*时,Python会把它截断成一个整数,而在现代的64位系统中,指针不适合普通整数。
由于在Python中除了调用DLL函数之外,你不打算使用这个指针,所以我们不必在Python端重构我们的结构,相反,我们可以使用void*,这是指向任意数据的指针类型,在Python中,我们称之为c_void_p
在程序的顶部,加载DLL之后,考虑

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

(Note:我们可以省略第1行和第4行,因为Python很乐意假设参数类型为整型,并且DemoCppFunction不返回任何值,所以我们不尝试使用它的返回值,但是为了一致性,我们最好是显式的。)

相关问题