передача строк python, через cython, в C

Я пытаюсь написать модуль с некоторыми частями на 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? Ответы, указывающие на более простой способ решения фактической проблемы, которую я пытаюсь решить, также очень приветствуются :)

5
задан tehwalrus 21 November 2011 в 16:42
поделиться