移植Python 2.7代码调用C函数到Python 3.4

时间:2015-10-07 09:37:36

标签: python c python-3.x shared-libraries ctypes

我正在尝试.so调用来自Python 3.4文件的C函数。我做了一些必要的更改,以使Python 2.7代码与Python 3.4一起使用,但我仍然遇到了Fatal Python error: Segmentation fault

代码来自此Bitbucket hosted project。我已经通过pip3(pip3 install Lemmagen)安装了它,它也创建了我试图从Python3使用的.so文件。

这是原始的Python2.7代码(调用C代码的函数),它可以从命令行运行python

def lemmatize(self, word):
    if (self._output_buffer_len < 2 * len(word)):
        self._output_buffer_len = 2 * len(word)
        self._output_buffer = create_string_buffer(self._output_buffer_len)

    is_unicode = isinstance(word, unicode)
    if is_unicode:
        word = word.encode('utf-8')

    self._lib.lem_lemmatize_word(word, self._output_buffer)
    return self._output_buffer.value.decode('utf-8') if is_unicode else self._output_buffer.value

这就是我试图让它适应Python3.4的方式:

def lemmatize(self, word):
    if (self._output_buffer_len < 2 * len(word)):
        self._output_buffer_len = 2 * len(word)
        self._output_buffer = create_string_buffer(self._output_buffer_len)

    word = word.encode('utf-8')


    self._lib.lem_lemmatize_word(word, self._output_buffer) #SEGFAULT HERE!
    #return "HERE"
    return self._output_buffer.value.decode('utf-8')

我删除了检查word是否为unicode的行,因为Unicode是Python3.x中的默认值。我仍然80%确定这是字符编码问题。我必须使用什么编码来将字符串变量传递给函数调用 self._lib.lem_lemmatize_word(word, self._output_buffer)?这是发生分段错误的确切行:

致命Python错误:分段错误

Current thread 0xb754b700 (most recent call first):
  File "/usr/local/lib/python3.4/dist-packages/lemmagen/lemmatizer.py", line 66 in lemmatize
  File "<stdin>", line 1 in <module>
Segmentation fault (core dumped)

我一直在尝试阅读我的确切问题(编码类型),但到目前为止我找到的任何内容似乎都没有解决这个问题。我会很感激这方面的一些有用的信息。谢谢。

感谢所有在没有任何理由或评论的情况下对该问题进行投票的人。

1 个答案:

答案 0 :(得分:2)

您需要使用create_string_buffer函数在将char数组传递给函数之前创建它。

这样的事情应该有效:

    import ctypes

class Lib:
    def __init__(self):
        self.lib = ctypes.cdll.LoadLibrary('/home/pim/slovene_lemmatizer/bin/libLemmatizer.so')


def lemmatize(self, word):
    text = "text"
    output_buffer = ctypes.create_string_buffer(text.encode())

    word_buffer = ctypes.create_string_buffer(word.encode())

    self.lib.lem_lemmatize_word(word, output_buffer)

    print("test")

def main():
    lib = Lib()
    lib.lemmatize("test")


if __name__ == '__main__':
    main()

此输出:

pim@pim-desktop:~/slovene_lemmatizer/bin$ python3 main.py [ERROR] Language file for lemmatizer has to be loaded first! test pim@pim-desktop:~/slovene_lemmatizer/bin$

编辑:我不能100%确定使用&#39; raw&#39;这里的财产是正确的,但它的确有效! Edit2:它在没有raw属性的情况下工作,更新了awnser