【问题标题】:How to avoid Segmentation error with Ctypes如何避免 Ctypes 的分段错误
【发布时间】:2022-06-16 02:43:23
【问题描述】:

我正在尝试通过 Python 运行以下 C 函数并得到分段错误。


void WKMV(
    const double *const time2,
    const int *const status,
    const double *const weights,
    const int *const delta,
    const int *const len,
    const int *const end,
    double *const surv)
{
    register int i;
    double n, d;
    *surv = 1;
    for (i = *len-1, n = 0; i >= *end; i--) { // loop in reverse order until end index is reached
        n += delta[i]*weights[i]; // initialize living weighting
    }
    while (i >= 0) { // loop through the sample in reverse order until zero index is reached
        n += delta[i]*weights[i];
        d = status[i]*weights[i]; // initialize dead weighting
        for (i--; i >= 0 && time2[i] == time2[i+1]; i--) { // loop in reverse order until time changes or zero index is reached
            n += delta[i]*weights[i]; // weight the living
            d += status[i]*weights[i]; // weight the dead
        }
        if (n > 0) *surv *= 1-d/n; // compute survival probability
    }
    return;

我正在像这样使用 Python Ctypes 包。为了方便起见,我为每个参数添加了硬编码数据。


from ctypes import *

c_funcs = CDLL('filepath/file.so')
WKMV = c_funcs.WKMV

def do_WKMV_using_c():


    """Call C function"""

    n = 10

    # Declaring the variables
    time2 = [58.72, 41.9, 16.23, 145.44, 10.56, 54.95, 196.46, 194.03, 20.95, 20.0]
    status = [1, 1, 0, 0, 0, 0, 0, 0, 1, 0]
    time1 = [6.36, 4.91, 6.53, 4.77, 5.59, 6.9, 3.05, 6.17, 5.19, 6.41]
    delta = [1]*n
    weights = [0.5]*n
    surv = 1.0


    #Converting variables to format readable to C
    c_arr_time2 = (c_double * n)(*time2)
    c_arr_status = (c_int * n)(*status)
    c_arr_weights = (c_double * n)(*weights)
    c_arr_delta = (c_int * n)(*delta)
    c_int_len = c_int(n)
    c_float_surv = c_double(surv)
    c_int_end = c_int(n)

    WeightedKaplanMeierValue.restype = None
    WeightedKaplanMeierValue(c_arr_time2,c_arr_status, c_arr_weights, c_arr_delta,
                             c_int_len, c_int_end, c_float_surv)

    c_res_out = c_float_surv

    return c_res_out

print(do_WKMV_using_c())

我收到以下错误

Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)

从外观上看,我已将所有参数翻译成可读的 C 代码。另外,正如我所看到的(我是 C 的菜鸟),C 函数中没有内部函数。所以不确定错误在哪里。还有没有办法从 C 中获取更详细的错误消息?有什么帮助吗?

【问题讨论】:

  • 您是否尝试过在 C 中单独测试该函数,而不涉及 Python?

标签: python c segmentation-fault ctypes


【解决方案1】:

错误未设置.argtypes,因此ctypes 可以检查参数是否正确传递。如果设置,它将通知您最后三个参数不正确。这是修复:

test.py

from ctypes import *

c_funcs = CDLL('./test')
WeightedKaplanMeierValue = c_funcs.WKMV
WeightedKaplanMeierValue.argtypes = (POINTER(c_double), POINTER(c_int), POINTER(c_double),
                                     POINTER(c_int), POINTER(c_int), POINTER(c_int), POINTER(c_double))
WeightedKaplanMeierValue.restype = None

def do_WKMV_using_c():
    n = 10
    time2 = [58.72, 41.9, 16.23, 145.44, 10.56, 54.95, 196.46, 194.03, 20.95, 20.0]
    status = [1, 1, 0, 0, 0, 0, 0, 0, 1, 0]
    time1 = [6.36, 4.91, 6.53, 4.77, 5.59, 6.9, 3.05, 6.17, 5.19, 6.41]
    delta = [1]*n
    weights = [0.5]*n
    surv = 1.0

    #Converting variables to format readable to C
    c_arr_time2 = (c_double * n)(*time2)
    c_arr_status = (c_int * n)(*status)
    c_arr_weights = (c_double * n)(*weights)
    c_arr_delta = (c_int * n)(*delta)
    c_int_len = c_int(n)
    c_float_surv = c_double(surv)
    c_int_end = c_int(n)

    WeightedKaplanMeierValue(c_arr_time2, c_arr_status, c_arr_weights, c_arr_delta,
                             byref(c_int_len), byref(c_int_end), byref(c_float_surv)) # Pass the address of the variables.
    c_res_out = c_float_surv.value  # Add .value to extract the Python object.
    return c_res_out

print(do_WKMV_using_c())

test.c - 用于测试的 DLL

#ifdef _WIN32
#   define API __declspec(dllexport)
#else
#   define API
#endif

API void WKMV(
    const double *const time2,
    const int *const status,
    const double *const weights,
    const int *const delta,
    const int *const len,
    const int *const end,
    double *const surv)
{
    register int i;
    double n, d;
    *surv = 1;
    for (i = *len-1, n = 0; i >= *end; i--) { // loop in reverse order until end index is reached
        n += delta[i]*weights[i]; // initialize living weighting
    }
    while (i >= 0) { // loop through the sample in reverse order until zero index is reached
        n += delta[i]*weights[i];
        d = status[i]*weights[i]; // initialize dead weighting
        for (i--; i >= 0 && time2[i] == time2[i+1]; i--) { // loop in reverse order until time changes or zero index is reached
            n += delta[i]*weights[i]; // weight the living
            d += status[i]*weights[i]; // weight the dead
        }
        if (n > 0) *surv *= 1-d/n; // compute survival probability
    }
    return;
}

输出:

0.39999999999999997

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多