Cython调用libc.bsearch获取排序数组索引返回异常值,求修正
修正Cython中使用libc.bsearch获取数组索引的错误
你在使用Cython调用libc的bsearch函数获取排序数组索引时,得到了错误的内存地址数值而非正确索引,问题出在指针处理逻辑和setup.py的依赖疏漏上,以下是具体修正方案:
错误原因分析
- 指针转索引逻辑错误:
bsearch返回的是指向找到元素的内存指针,你直接将指针强制转换为int类型,得到的是该指针的内存地址值(即你看到的610183044),而非数组中的元素索引。正确做法是通过指针偏移计算索引:用找到的指针减去数组起始指针,利用C语言指针相减自动除以元素大小的特性,直接得到索引值。 - setup.py依赖缺失:代码中使用
np.get_include()但未导入numpy,编译时会触发NameError。
修正后的代码
test_bsearch.pyx
cimport cython from libc.stdlib cimport bsearch cdef int comp_fun(const void *a, const void *b) nogil: cdef int a_v = (<int*>a)[0] cdef int b_v = (<int*>b)[0] if a_v < b_v: return -1 elif a_v > b_v: return 1 else: return 0 def bsearch_c(int[::1] t, int v): cdef int *p = <int*> bsearch(&v, &t[0], t.shape[0], sizeof(int), &comp_fun) if p != NULL: # 通过指针偏移计算元素索引 return p - &t[0] else: return -1
setup.py
from distutils.core import setup from Cython.Build import cythonize import numpy as np # 必须导入numpy才能调用np.get_include() setup( ext_modules=cythonize([ "test_bsearch.pyx" ], compiler_directives={'language_level': "3"} ), include_dirs=[ np.get_include() ] )
测试验证
重新执行编译命令python setup.py build_ext -i,运行测试代码即可得到正确结果:
>>> from test_bsearch import bsearch_c >>> import numpy as np >>> x = np.arange(20, dtype=np.int32) >>> bsearch_c(x, 5) # 返回5,结果正确
内容的提问来源于stack exchange,提问作者Elkan
相关产品推荐
相关产品推荐

