簡體   English   中英

用 Cython 包裝 C header 宏

[英]Wrapping C header macros with Cython

我正在為 NAG C 庫編寫 Cython 包裝器。

在 NAG C 庫中的 header 文件之一是宏:

#define NAG_FREE(x) x04bdc((Pointer *)&(x))

指針無效*

x04bdc 是:

extern void NAG_CALL x04bdc(Pointer *ptr);

NAG_FREE 是相當於 free() 的 NAG 庫,用於釋放 memory。

這是我的 lib_nag_integrate.pxd 文件的摘錄:

cdef extern from "<nagx04.h>":
    void x04bdc(Pointer *ptr)

x04bdc 是一個“花哨的”免費 (malloc) 例程。 我無法訪問此代碼。

然后我在 my.pyx 文件中創建一個 cdef function :

cdef void NAG_FREE(double *x):
    x04bdc(<Pointer *>&x)

在這里,我將 x 類型轉換為雙指針,因為這是我試圖從 memory 中釋放出來的,但是 NAG 庫示例似乎將它用於任何類型的指針。

當運行 python 腳本調用最終使用 NAG_FREE 的 cpdef function 時,我收到以下錯誤:

Process finished with exit code 134 (interrupted by signal 6: SIGABRT)

如果我注釋掉 NAG_FREE 調用,那么它工作正常,但是 NAG 說有必要使用 NAG_FREE。

使用 NAG_FREE 的 cdef function 是:

cdef (double,double,Integer,Integer) dim1_fin_gen(lib_nag_integrate.NAG_D01SJC_FUN objfun,double a, double b,double epsabs, double epsrel,
                         Integer max_num_subint,Nag_User *comm,integration_out *output):
    """

    :param f: user function
    :type f: function
    :param a: lower limit of integration
    :type a: real float
    :param b: upper limit of integration
    :type b: real float
    :param epsabs: user requested absolute error
    :type epsabs: integer
    :param epsrel: user requested relative error
    :type epsrel: integer
    :param max_num_subint: maximum number of subintervals
    :type max_num_subint: real integer
    :return: integration value of user function f
    :rtype: real float
    """

    cdef lib_nag_integrate.Nag_QuadProgress _qp
    cdef lib_nag_integrate.NagError _fail
    cdef double result
    cdef double abserr


    _fail.print = True
    _fail.code = 0
    _fail.errnum = 0
    _fail.handler = NULL

    lib_nag_integrate.d01sjc(objfun, a, b, epsabs, epsrel,
                             max_num_subint, &result, &abserr,
                    &_qp, comm, &_fail)
    if _fail.code > 0 :
        errorMessage = _fail.message
        raise NagException(_fail.code,errorMessage)
        print(_fail.message)

    else:
        output[0].result = result
        output[0].abserr = abserr
        output[0].fun_count = _qp.fun_count
        output[0].num_subint = _qp.num_subint

        NAG_FREE(_qp.sub_int_beg_pts)
        NAG_FREE(_qp.sub_int_end_pts)
        NAG_FREE(_qp.sub_int_result)
        NAG_FREE(_qp.sub_int_error)

我的 libnag_integrate.pxd header 文件從 c 庫中導入以下內容:

cdef extern from "<nag_types.h>":
    ctypedef bint Nag_Boolean
    ctypedef long Integer
    ctypedef void* Pointer
    ctypedef struct NagError:
        int code
        bint print "print"
        char message[512]
        Integer errnum
        void (*handler)(char*,int,char*)
    ctypedef struct Nag_User:
        Pointer p
    ctypedef struct Nag_QuadProgress:
        Integer num_subint
        Integer fun_count
        double *sub_int_beg_pts
        double *sub_int_end_pts
        double *sub_int_result
        double *sub_int_error

cdef extern from "<nagx04.h>":
    (void*) NAG_ALLOC "x04bjc" (size_t size)
    void x04bdc(Pointer *ptr)


cdef extern from "<nagd01.h>":
    void d01sjc(NAG_D01SJC_FUN f, double a, double b,
         double epsabs, double epsrel, Integer max_num_subint, double *result,
         double *abserr, Nag_QuadProgress *qp, Nag_User *comm,
         NagError *fail)

d01sjc 是我無法訪問的集成例程。 它在里面分配qp.sub_int_beg_pts等的memory。

我想我有一個損壞的指針導致錯誤。 如果是這樣,它在哪里以及如何修復它?

非常感謝

進一步檢查結構“_qp”。 取消引用時會發生相同的錯誤,例如:

x = _qp.sub_int_end_pts[0]

所以它是導致錯誤的 _qp 的取消引用。

結構類型 Nag_QuadProgress 從其 NAG header 文件導入到 my.pxd 中,如下所示:

cdef extern from "<nag_types.h>":
ctypedef struct Nag_QuadProgress:
        Integer num_subint
        Integer fun_count
        double *sub_int_beg_pts
        double *sub_int_end_pts
        double *sub_int_result
        double *sub_int_error

任何想法為什么取消引用此結構中的指針會導致錯誤?

從 Cython 的角度來看,您將NAG_FREE用作 function,因此您應該將其聲明為。 它是一個真正的宏並不重要,嘗試重新實現它當然也無濟於事。

cdef extern from "whatever_the_nag_header_is":
    void NAG_FREE(Pointer x)
    # or
    void NAG_FREE(void *x)
    # or
    void NAG_FREE(...)  # accepts anything - Cython doesn't attempt to match types

您可能需要嘗試使用 arguments 的類型才能使其工作 - 我建議了三個選項。

實際上,您要做的就是為 Cython 提供足夠的信息,使其可以生成正確的 C 代碼,而正確的 C 代碼是NAG_FREE(your_variable) ,就好像它是 ZC1C425268E17A98 調用一樣。


使用您的代碼:

  • (<integration_out*>output)[0]表明你做錯了什么。 output一個integration_out指針,那么你為什么要轉換它呢? 它要么什么都不做,要么引入一個潛在的錯誤。

  • 盡管聲稱返回 C 元組類型,但您實際上並不費心返回任何東西。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM