Cython with Python3.5:将字符串列表转换为字符**
我试图把字符串列表传递给C++函数,它使用Cython作为char **。 我尝试了其他解决方案,但我记不得了,但我主要尝试了以下两种方案:Cython with Python3.5:将字符串列表转换为字符**,python,python-3.x,type-conversion,cython,wrapper,Python,Python 3.x,Type Conversion,Cython,Wrapper,我试图把字符串列表传递给C++函数,它使用Cython作为char **。 我尝试了其他解决方案,但我记不得了,但我主要尝试了以下两种方案: 在g++编译中使用从中提取的转换函数,这与答案基本相同,但会引发一个错误 cy_wrapper.cpp: In function 'char** _pyx_f_10cy_wrapper_to_cstring_array(PyObject*)': cy_wrapper.cpp:1223:44: error 'PyString_AsString' was no
g++
编译中使用从中提取的转换函数,这与答案基本相同,但会引发一个错误
cy_wrapper.cpp: In function 'char** _pyx_f_10cy_wrapper_to_cstring_array(PyObject*)':
cy_wrapper.cpp:1223:44: error 'PyString_AsString' was not declared in this scope
__pyx_t_5 = PyString_AsString(__pyx_t_4); if (unlikely(__pyx_t_5 == ((char *)NULL))
cy_wrapper.pyx:14:35: Storing unsafe C derivative of temporary Python reference
~/.local/lib/python3.5/site packages/Cython/Includes/cpython
的库文件中找到了包含我需要的函数PyString\u的文件string.pxd
为什么找不到?如果不可能使用它,是否有解决方法
我正在arm64 arch上开发Ubuntu16.04.4LTS(tegra内核)
我的cy\u wrapper.pyx
与此完全相同:
来自cpython.string cimport PyString\u AsString
来自libc.stdlib cimport malloc
cdef外部人员:
cdef cppclass imageNet:
imageNet*创建(整数argc,字符**argv)
cdef字符**到数组(列表):
cdef char**ret=malloc(len(list_str)*sizeof(char*))
对于范围内的i(len(list_str)):
ret[i]=PyString\u AsString(list\u str[i])
回程网
cdef类PyImageNet:
cdef图像网*c_网
def创建(自身、argc、kwargs):
cdef字符**c_argv=到_cstring_数组(kwargs)
返回PyImageNetFactory(self.c_net.Create(argc,c_argv))
cdef对象PyImageNetFactory(imageNet*ptr):
cdef PyImageNet py_obj=PyImageNet()
py_obj.c_net=ptr
返回py_obj
Mysetup.py
:
来自distutils.core导入设置
从distutils.extension导入扩展
从Cython.Distutils导入生成\u ext
设置(
cmdclass={“build\u ext”:build\u ext},
外部模块=[
扩展(“cy_包装器”,
sources=[“cy_wrapper.pyx”],
库=[“共享推理”],
language=“c++”,
额外参数=[“-O3”,“-Wall”],
额外链接参数=[“-L../build/”]
)
]
)
Ofclibshared\u推断。因此,
位于./build/
中,并定义了类imageNet
,对于那些感兴趣的人,下面是我如何将我的字符串列表
转换为字符**
(我忘了在问题中提到我的方法是静态的,但对于我的解决方案来说这并不重要),希望这能帮助别人
# cy_wrapper.pyx
from libc.stdlib cimport malloc, free
cdef extern:
cdef cppclass imageNet:
@staticmethod
imageNet* Create(int argc, char** argv)
cdef class PyImageNet:
cdef imageNet* c_net
@staticmethod
def Create(args):
# Declare char**
cdef char** c_argv
# Allocate memory
c_argv = <char**>malloc(len(args) * sizeof(char*))
# Check if allocation went fine
if c_argv is NULL:
raise MemoryError()
# Convert str to char* and store it into our char**
for i in range(len(args)):
args[i] = args[i].encode()
c_argv[i] = args[i]
# Grabbing return value
cdef imageNet* c_tmp_net = imageNet.Create(len(args), c_argv)
# Let him go
free(c_argv)
# Return python-compatible value
return PyImageNetFactory(c_tmp_net)
cdef object PyImageNetFactory(imageNet* ptr):
cdef PyImageNet py_obj = PyImageNet()
py_obj.c_net = ptr
return py_obj
问题在于,PyString\u AsString
是python2的功能,而python3中没有。Cython文档在这里介绍了这个主题:这里还隐藏了一个内存管理灾难(正如“存储临时Python引用的不安全C派生代码”警告您的那样)。在这两种情况下,内存都属于Python字符串,因此只有Python对象有效时,内存才有效。
# test.py
import cy_wrapper
args = ["str1", "str2"]
net = cy_wrapper.PyImageNet.Create(args)