Я пытаюсь написать модуль с некоторыми частями на c и некоторыми частями на python. Я использую cython для преодоления разрыва.
Я хочу хранить мои (очень длинные) строковые константы в python, потому что синтаксис намного приятнее:
const char long_string = "\npart of string\n"
"next part\n"
"last part\n";
против:
long_string = """
part of string
next part
last part
"""
(строки намного длиннее, чем эти, и сложнее - до такой степени, что я не хочу добавлять и удалять "
s и \n"
s каждый раз, когда я хочу отредактировать их с подсветкой синтаксиса. На самом деле, это ядра openCL.)
Мне нужно иметь возможность превратить их в строки c с помощью cython, и согласно документации мне нужно только это:
cdef bytes py_bytes = py_string.encode()
cdef char* c_string = py_bytes
и без ручного управления памятью, c_string
будет работать, пока я держу ссылку на py_bytes
.
Однако я не могу заставить это работать с простым тестом printf. Вот мой файл cython:
cdef extern from "stdio.h":
printf(char* string)
def go():
py_string = """
a complicated string
with a few
newlines.
"""
cdef bytes py_bytes = py_string.encode()
cdef char* c_string = py_bytes
printf(c_string)
print "we don't get this far :("
который при компиляции во время выполнения с помощью pyximport
дает следующий вывод на терминал перед сегфаултом:
a complicated string
with a few
newlines.
Segmentation fault: 11
теперь, я проверил, что cython на самом деле помещает в файл c, и попробовал это в ванильном файле C, где не происходит segfault:
#include "stdio.h"
static char __pyx_k_1[] = "\na complicated string\nwith a few\nnewlines.\n";
int main(void) {
void* output = printf(__pyx_k_1);
if (!output) {
printf("apparently, !output.");
}
}
чтобы быть ясным, cython генерирует код, который ловит вывод printf
и проверяет на "не это". Тип переменной - PyObject*
.
Моя единственная догадка здесь была в том, что строка была неправильно завершена, поэтому printf просто проходит мимо ее конца и вызывает segfault, но поскольку этого не происходит в моем тесте на чистом c, я в полном тупике.
Итак, мой вопрос в том, как мне действительно передать c-строку в c-код из cython? Ответы, указывающие на более простой способ решения фактической проблемы, которую я пытаюсь решить, также очень приветствуются :)