使用 ctypes 将 Python 元组传递给 C++ 函数时出现分段错误 11
Segmentation fault 11 when pass a Python tuple to C++ function with ctypes
我正在尝试使用 Python ctypes 在 Python 代码中调用一些 C++ 函数。我有两个代码文件:一个是core_lib.cpp,它定义了一个class和一个成员方法;另一个是demo.py,它实例化class并调用成员方法。
core_lib.cpp定义如下
#include <iostream>
#include <tuple>
using namespace std;
class A {
private:
string _name;
tuple<int, int> _size;
public:
A() {
this->_name = "";
this->_size = make_tuple(1, 1);
cout << "Init values of _size: " << get<0>(this->_size) << ", " << get<1>(this->_size) << endl;
}
void set_size(int* size) {
int a = *size;
int b = *(size+1);
this->_size = make_tuple(a, b);
cout << "New values of _size: " << get<0>(this->_size) << ", " << get<1>(this->_size) << endl;
}
};
// bridge C++ to C
extern "C" {
A* create_A() {
return new A();
}
void set_size(A* a, int* size) {
a->set_size(size);
}
}
demo.py定义如下
from ctypes import *
import os
# load C++ lib
core_lib = cdll.LoadLibrary(os.path.abspath('test/Whosebug/core_lib.so'))
class A(object):
def __init__(self):
self.a = core_lib.create_A()
def set_size(self, size):
core_lib.set_size(self.a, size)
if __name__ == "__main__":
asize = (3, 3)
size = (c_int * 2)(*asize)
a = A()
a.set_size(size)
为了重现该问题,我在此处列出了我的步骤:
- 编译core_lib.cpp:
g++ core_lib.cpp -fPIC -shared -std=c++11 -o core_lib.so
- 运行 python 脚本:python demo.py
Python 版本为 2.7.15,在 MacOS Mojave 上运行。
根据我的调查,问题是由 core_lib.cpp 中的代码行引起的:
this->_size = make_tuple(a, b)
我试图 google 这个问题,但没有找到答案。如果有任何有助于理解问题和解决方法的评论,我将不胜感激。
为您的函数定义 .argtypes
和 .restype
。默认类型是 c_int
(32 位),您可能正在使用 OS,其中指针是 64 位,截断 A*
return 值。
core_lib.create_A.argtypes = None
core_lib.create_A.restype = c_void_p
core_lib.set_size.argtypes = [c_void_p,POINTER(c_int)]
core_lib.set_size.restype = None
c_void_p
对于不透明指针就足够了。您可以通过声明一个指向 class 的指针并将大小指针声明为两个整数的数组来获得更好的类型检查:
class A(Structure):
pass
core_lib.create_A.argtypes = None
core_lib.create_A.restype = POINTER(A)
core_lib.set_size.argtypes = POINTER(A),POINTER(c_int * 2)
core_lib.set_size.restype = None
如果你有选择,我建议定义set_size
为void set_size(A* a, int x, int y)
这样你就可以直接调用a.set_size(3,3)
而不是创建一个(c_int * 2)(3,3)
来传递。
我正在尝试使用 Python ctypes 在 Python 代码中调用一些 C++ 函数。我有两个代码文件:一个是core_lib.cpp,它定义了一个class和一个成员方法;另一个是demo.py,它实例化class并调用成员方法。
core_lib.cpp定义如下
#include <iostream>
#include <tuple>
using namespace std;
class A {
private:
string _name;
tuple<int, int> _size;
public:
A() {
this->_name = "";
this->_size = make_tuple(1, 1);
cout << "Init values of _size: " << get<0>(this->_size) << ", " << get<1>(this->_size) << endl;
}
void set_size(int* size) {
int a = *size;
int b = *(size+1);
this->_size = make_tuple(a, b);
cout << "New values of _size: " << get<0>(this->_size) << ", " << get<1>(this->_size) << endl;
}
};
// bridge C++ to C
extern "C" {
A* create_A() {
return new A();
}
void set_size(A* a, int* size) {
a->set_size(size);
}
}
demo.py定义如下
from ctypes import *
import os
# load C++ lib
core_lib = cdll.LoadLibrary(os.path.abspath('test/Whosebug/core_lib.so'))
class A(object):
def __init__(self):
self.a = core_lib.create_A()
def set_size(self, size):
core_lib.set_size(self.a, size)
if __name__ == "__main__":
asize = (3, 3)
size = (c_int * 2)(*asize)
a = A()
a.set_size(size)
为了重现该问题,我在此处列出了我的步骤:
- 编译core_lib.cpp: g++ core_lib.cpp -fPIC -shared -std=c++11 -o core_lib.so
- 运行 python 脚本:python demo.py
Python 版本为 2.7.15,在 MacOS Mojave 上运行。
根据我的调查,问题是由 core_lib.cpp 中的代码行引起的:
this->_size = make_tuple(a, b)
我试图 google 这个问题,但没有找到答案。如果有任何有助于理解问题和解决方法的评论,我将不胜感激。
为您的函数定义 .argtypes
和 .restype
。默认类型是 c_int
(32 位),您可能正在使用 OS,其中指针是 64 位,截断 A*
return 值。
core_lib.create_A.argtypes = None
core_lib.create_A.restype = c_void_p
core_lib.set_size.argtypes = [c_void_p,POINTER(c_int)]
core_lib.set_size.restype = None
c_void_p
对于不透明指针就足够了。您可以通过声明一个指向 class 的指针并将大小指针声明为两个整数的数组来获得更好的类型检查:
class A(Structure):
pass
core_lib.create_A.argtypes = None
core_lib.create_A.restype = POINTER(A)
core_lib.set_size.argtypes = POINTER(A),POINTER(c_int * 2)
core_lib.set_size.restype = None
如果你有选择,我建议定义set_size
为void set_size(A* a, int x, int y)
这样你就可以直接调用a.set_size(3,3)
而不是创建一个(c_int * 2)(3,3)
来传递。