通过 ctypes 在 Python 中导入 C++ 函数:为什么会出现分段错误?
Import C++ function in Python through ctypes: why segmentation fault?
我试图从 Python
调用这个 C++
文件 (myfunc.cpp)。我决定使用 ctypes
模块,因为它似乎对 C
和 C++
代码都工作得很好。
我遵循了几个教程(例如 ),其中建议在要在 Python
.[=24= 中调用的 C++
函数顶部添加 'extern C
' ]
#include <iostream>
#include <cmath>
#include <vector>
#include <cstdio>
using namespace std;
int from_xy(int x, int y, int nside) {
return x + (nside * y);
}
std::vector<int> to_xy(int k, int nside) {
int x = k%nside;
int y = floor(k / nside);
vector<int> res(x, y);
return res;
}
int modNegOperator(int k, int n){
return ((k %= n) < 0) ? k+n : k;
}
extern "C"
double** create2Darray(unsigned nside, double mx, double my) {
int n_matrix = nside * nside;
double **array2D = 0;
array2D = new double *[n_matrix];
for (int h = 0; h < n_matrix; h++) {
array2D[h] = new double[n_matrix];
for (int w = 0; w < n_matrix; w++) {
// fill in some initial values
// (filling in zeros would be more logic, but this is just for the example)
array2D[h][w] = 0;
}
}
for (int h = 0; h < n_matrix; h++){
std::vector<int> xy_vec = to_xy(h, nside);
int modneg1 = modNegOperator(xy_vec[0] + 1,nside);
int modneg2 = modNegOperator(xy_vec[0] - 1,nside);
int modneg3 = modNegOperator(xy_vec[1] + 1,nside);
int modneg4 = modNegOperator(xy_vec[1] - 1,nside);
int pos1 = from_xy(modneg1, xy_vec[1], nside);
int pos2 = from_xy(modneg2, xy_vec[1], nside);
int pos3 = from_xy(xy_vec[0], modneg3, nside);
int pos4 = from_xy(xy_vec[0], modneg4, nside);
double half_mx = mx / 2;
double half_my = my / 2;
array2D[h][h] = 0;
array2D[h][pos1] = half_mx;
array2D[h][pos2] = half_mx;
array2D[h][pos3] = half_my;
array2D[h][pos4] = half_my;
}
return array2D;
}
然后我创建了一个共享库:
g++ -fPIC -shared -o libTest.so myfunc.cpp
创建了一个 myLib.py 文件,其中包括:
import ctypes
import sys
import os
dir_path = os.path.dirname(os.path.realpath(__file__))
handle = ctypes.CDLL(dir_path + "/libTest.so")
handle.create2Darray.argtypes = [ctypes.c_int, ctypes.c_double, ctypes.c_double]
def create2Darray(nside, mx, my):
return handle.create2Darray(nside, mx, my)
但是,当我尝试 运行 我在 python 中的函数时:
from myLib import *
create2Darray(4, 0.01,0.01)
我得到 'Segmentation fault'.
你知道我做错了什么吗?你有什么建议吗?或者也许建议另一种方法,我可以用它在 python 中导入我的 C++ 函数。当然,另一种选择是用 C 语言重写代码。
正如我们在聊天中提到的那样,问题中发布的代码会出现段错误,因为以下代码 return 在首次调用时是一个 zero-length 向量:
std::vector<int> to_xy(int k, int nside) {
int x = k%nside;
int y = floor(k / nside);
vector<int> res(x, y); // if k==0, this is length 0
return res;
}
然后这段代码在这里出错:
for (int h = 0; h < n_matrix; h++){
std::vector<int> xy_vec = to_xy(h, nside); // length 0
int modneg1 = modNegOperator(xy_vec[0] + 1,nside); // xy_vec[0] faults.
我们在聊天中讨论的代码没有失败,因为:
vector<int> res(x, y); // if k==0, this is length 0
已更改为:
vector<int> res{x, y}; // curly braces, length 2
解决后,Python 代码只需要 .restype
定义,技术上 c_uint
第一个参数:
handle.create2Darray.argtypes = ctypes.c_uint, ctypes.c_double, ctypes.c_double
handle.create2Darray.restype = ctypes.POINTER(ctypes.POINTER(ctypes.c_double))
然后代码会 return 正确 double**
。
我试图从 然后我创建了一个共享库: 创建了一个 myLib.py 文件,其中包括: 但是,当我尝试 运行 我在 python 中的函数时: 我得到 'Segmentation fault'. 你知道我做错了什么吗?你有什么建议吗?或者也许建议另一种方法,我可以用它在 python 中导入我的 C++ 函数。当然,另一种选择是用 C 语言重写代码。Python
调用这个 C++
文件 (myfunc.cpp)。我决定使用 ctypes
模块,因为它似乎对 C
和 C++
代码都工作得很好。
我遵循了几个教程(例如 Python
.[=24= 中调用的 C++
函数顶部添加 'extern C
' ]
#include <iostream>
#include <cmath>
#include <vector>
#include <cstdio>
using namespace std;
int from_xy(int x, int y, int nside) {
return x + (nside * y);
}
std::vector<int> to_xy(int k, int nside) {
int x = k%nside;
int y = floor(k / nside);
vector<int> res(x, y);
return res;
}
int modNegOperator(int k, int n){
return ((k %= n) < 0) ? k+n : k;
}
extern "C"
double** create2Darray(unsigned nside, double mx, double my) {
int n_matrix = nside * nside;
double **array2D = 0;
array2D = new double *[n_matrix];
for (int h = 0; h < n_matrix; h++) {
array2D[h] = new double[n_matrix];
for (int w = 0; w < n_matrix; w++) {
// fill in some initial values
// (filling in zeros would be more logic, but this is just for the example)
array2D[h][w] = 0;
}
}
for (int h = 0; h < n_matrix; h++){
std::vector<int> xy_vec = to_xy(h, nside);
int modneg1 = modNegOperator(xy_vec[0] + 1,nside);
int modneg2 = modNegOperator(xy_vec[0] - 1,nside);
int modneg3 = modNegOperator(xy_vec[1] + 1,nside);
int modneg4 = modNegOperator(xy_vec[1] - 1,nside);
int pos1 = from_xy(modneg1, xy_vec[1], nside);
int pos2 = from_xy(modneg2, xy_vec[1], nside);
int pos3 = from_xy(xy_vec[0], modneg3, nside);
int pos4 = from_xy(xy_vec[0], modneg4, nside);
double half_mx = mx / 2;
double half_my = my / 2;
array2D[h][h] = 0;
array2D[h][pos1] = half_mx;
array2D[h][pos2] = half_mx;
array2D[h][pos3] = half_my;
array2D[h][pos4] = half_my;
}
return array2D;
}
g++ -fPIC -shared -o libTest.so myfunc.cpp
import ctypes
import sys
import os
dir_path = os.path.dirname(os.path.realpath(__file__))
handle = ctypes.CDLL(dir_path + "/libTest.so")
handle.create2Darray.argtypes = [ctypes.c_int, ctypes.c_double, ctypes.c_double]
def create2Darray(nside, mx, my):
return handle.create2Darray(nside, mx, my)
from myLib import *
create2Darray(4, 0.01,0.01)
正如我们在聊天中提到的那样,问题中发布的代码会出现段错误,因为以下代码 return 在首次调用时是一个 zero-length 向量:
std::vector<int> to_xy(int k, int nside) {
int x = k%nside;
int y = floor(k / nside);
vector<int> res(x, y); // if k==0, this is length 0
return res;
}
然后这段代码在这里出错:
for (int h = 0; h < n_matrix; h++){
std::vector<int> xy_vec = to_xy(h, nside); // length 0
int modneg1 = modNegOperator(xy_vec[0] + 1,nside); // xy_vec[0] faults.
我们在聊天中讨论的代码没有失败,因为:
vector<int> res(x, y); // if k==0, this is length 0
已更改为:
vector<int> res{x, y}; // curly braces, length 2
解决后,Python 代码只需要 .restype
定义,技术上 c_uint
第一个参数:
handle.create2Darray.argtypes = ctypes.c_uint, ctypes.c_double, ctypes.c_double
handle.create2Darray.restype = ctypes.POINTER(ctypes.POINTER(ctypes.c_double))
然后代码会 return 正确 double**
。