Python 3 で使用できるように、CPython に Cython 拡張機能を記述して 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
暗号化を行うためのコピーを作成し、次に戻り値への 2 番目のコピーを作成するため、これはおそらく世界で最も効率的なコードではありません。ただし、それを回避できるかどうかはわかりません。新しく割り当てられたバッファを取り、それをバイト文字列としてインプレースで Python に返すことができるかどうかわからないからです。しかし、機能する機能ができたので、ブロックごとの方法も実装して、暗号化または復号化のために反復可能なブロックを提供し、ソース全体がなくても実行できるようにします一度にすべての宛先をメモリ内に保存する---そうすれば、任意の時点で最大3つのコピーをメモリに保持することを心配することなく、巨大なファイルを暗号化/復号化できます...
助けてくれてありがとう、みんな!