Я пытаюсь написать расширение Cython для CPython, чтобы обернуть библиотеку mcrypt, чтобы я мог использовать ее с Python 3. Однако я сталкиваюсь с проблемой, когда у меня возникает ошибка при попытке использовать один из API mcrypt.
Код, который не работает:
def _real_encrypt(self, source):
src_len = len(source)
cdef char* ciphertext = source
cmc.mcrypt_generic(self._mcStream, <void *>ciphertext, src_len)
retval = source[:src_len]
return retval
Теперь, как я понимаю в документации по Cython, назначение в строке 3 должно копировать содержимое буфера (объект в Python 3) в указатель строки C. Я бы подумал, что это также будет означать, что он будет выделять память, но когда я сделал эту модификацию:
def _real_encrypt(self, source):
src_len = len(source)
cdef char* ciphertext = <char *>malloc(src_len)
ciphertext = source
cmc.mcrypt_generic(self._mcStream, <void *>ciphertext, src_len)
retval = source[:src_len]
return retval
он все еще падал с ошибкой. Он выходит из строя внутри mcrypt_generic, но когда я использую простой код C, я могу заставить его работать нормально, поэтому должно быть что-то, чего я не совсем понимаю о том, как Cython работает с данными C здесь.
Спасибо за любую помощь!
ETA : проблема заключалась в ошибке с моей стороны. Я работал над этим после того, как проснулся слишком много часов (разве это не то, что мы все сделали в какой-то момент?) И пропустил что-то глупое. Код, который у меня сейчас есть, работает:
def _real_encrypt(self, source):
src_len = len(source)
cdef char *ciphertext = <char *>malloc(src_len)
cmc.strncpy(ciphertext, source, src_len)
cmc.mcrypt_generic_init(self._mcStream, <void *>self._key,
len(self._key), NULL)
cmc.mcrypt_generic(self._mcStream, <void *>ciphertext,
src_len)
retval = ciphertext[:src_len]
cmc.mcrypt_generic_deinit(self._mcStream)
return retval
Вероятно, это не самый эффективный код в мире, поскольку он создает копию для шифрования, а затем вторую копию возвращаемого значения. Однако я не уверен, что этого можно избежать, поскольку я не уверен, можно ли взять вновь выделенный буфер и вернуть его в Python на месте в качестве строки байтов. Но теперь, когда у меня есть рабочая функция, я собираюсь также реализовать блочный метод, чтобы можно было предоставлять итерируемые блоки для шифрования или дешифрования, и иметь возможность делать это, не имея всего источника и назначение целиком в памяти все сразу - таким образом, было бы возможно зашифровать / расшифровать огромные файлы, не беспокоясь о том, чтобы хранить до трех копий в памяти в любой точке ...
Спасибо за помощь, всем!