繁体   English   中英

import C++ function in Python through ctypes: why segmentation fault?

[英]Import C++ function in Python through ctypes: why segmentation fault?

我试图从Python调用这个C++文件(myfunc.cpp)。 我决定使用ctypes模块,因为它似乎适用于CC++代码。 我遵循了几个教程(例如, 从 Python 调用 C++ 代码的现代/2020 方式),建议在 C++ function 的顶部添加' extern C ' 以在C++ Python中调用

#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 中运行我的 function 时:

from myLib import *
create2Darray(4, 0.01,0.01)

我得到“分段错误”。

你知道我做错了什么吗? 你有什么建议吗? 或者也许建议另一种方法,我可以用它在 python 中导入我的 C++ function。当然,另一种方法是重写 C 中的代码。

正如我们在聊天中提到的,问题中发布的代码存在段错误,因为以下代码在首次调用时返回零长度向量:

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

然后代码将正确返回double**

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM