Я пытаюсь понять, как передавать строковые значения между Python3 и функции C ++. Однако я не могу собрать библиотеку с помощью Cython.
В частности, я не понял, как объявить возвращаемое значение строки и строковый параметр в source.pyx
, С типом int он работает правильно.
Ошибка, которую я получаю при сборке с помощью clang, заключается в следующем:
candidate function not viable: no known conversion from 'PyObject *' (aka '_object *') to 'char *' for 1st argument
мой source.pyx
является следующим:
cdef extern from "source.cpp":
cdef str fun(str param)
def pyfun(mystring):
return fun(mystring)
мой source.cpp
является:
char * fun(char *string) {
return string;
}
Помимо ошибок в исходном коде, мне удалось заставить его работать со следующими source.pyx
(перевод между bytes
введите Python3 и char*
в C ++):
cdef extern from "source.cpp":
cdef char* fun(char* param)
def pyfun(mystring):
mystring_b = mystring.encode('utf-8')
rvalue = fun(mystring_b).decode('utf-8')
return rvalue
Если память выделена с помощью malloc
в fun
он также должен быть освобожден, иначе произойдет утечка памяти (при работе с указателями Си всегда стоит подумать, кому принадлежит память). Модифицированная версия, которая делает это:
from libc.stdlib cimport free
# cdef extern as before
def pyfun(mystring):
cdef char* value_from_fun
mystring_b = mystring.encode('utf-8')
value_from_fun = fun(mystring_b)
try:
return value_from_fun.decode('utf-8')
finally:
free(value_from_fun)
Преобразования типов действуют так же, как и раньше.
Согласно hpauljкомментарий в оригинальном вопросе, вот версия с libcpp.string
какие карты C ++ std::string
определяется в <string>
:
from libcpp.string cimport string
cdef extern from "source.cpp":
cdef string fun(string param)
def pyfun(mystring):
mystring_ = mystring.encode('utf-8')
rvalue = fun(mystring_).decode('utf-8')
return rvalue
Других решений пока нет …