我想写一个Cython扩展到CPython来包装mcrypt库,以便我可以在Python 3中使用它。但是,我遇到了一个问题,当我尝试使用段错误其中一个mcrypt API。Cython字节到C字符*
发生故障的代码是:
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。但是现在我有了一个工作函数,我也要实现一个逐块的方法,这样就可以提供一个用于加密或解密的可迭代块,并且能够在不需要整个源的情况下完成和目的地全部在内存中 - 这样,就可以加密/解密大文件,而不必担心在任何一个点上最多可以在内存中保存三份...
感谢大家的帮助!
...这就是为什么我可能应该昨晚睡觉,因为我试图编程,而过度疲劳。事实上,它的工作原理是对strncpy(我使用的原因是输入中有NULL字节的可能性)的调用,然后我可以调用mcrypt_generic,将输出复制到Python字节串中,释放临时缓冲区,并返回。感谢这个答案,它指出了我正确的方向。 – 2010-12-14 15:16:05
!!!如果输入中可以有效地使用空字节,'strncpy'将**不会**帮助你。这意味着你的输入根本不是一个字符串,而是一串字节。使用'memcpy'或类似的东西。 – 2010-12-14 15:24:52
哦,你是绝对正确的; n是“高达”。哦,废话。哦,哦,废话。我想你可能只是指出我的错误,我张贴在另一个问题:http://stackoverflow.com/questions/4451977/data-corruption-wheres-the-bug – 2010-12-15 16:01:16