【问题标题】:Porting Python 2.7 code calling a C function to Python 3.4将调用 C 函数的 Python 2.7 代码移植到 Python 3.4
【发布时间】:2015-10-07 09:37:36
【问题描述】:

我正在尝试.so 文件中调用 C 函数Python 3.4。我已经进行了一些必要的更改以使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)

我一直在尝试阅读我的确切问题(编码类型),但到目前为止我没有发现任何东西似乎可以解决这个问题。我将不胜感激有关此的一些深思熟虑的信息。谢谢。

感谢任何人在没有理由或任何评论的情况下否决了这个问题。

【问题讨论】:

  • 可能值得添加一个事实,即您使用的是 ctypes,因此您调用的是 C 函数而不是 C++ 函数。
  • 好的,我会改正的。
  • @Pim @DrunkenMaster lem_lemmatize_word 在源代码中实际上定义为extern "C",因此通过 ctypes 调用它应该不成问题。
  • 我仍然不明白为什么会发生分段错误,我也尝试传递硬编码的b'string'u'string'。它们没有任何区别。
  • @Vovanrock2002 是的,但问题是它是一个 c++ 函数,它是。

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


【解决方案1】:

您需要使用 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% 确定此处“原始”属性的使用是否正确,但它确实有效! Edit2:它确实在没有原始属性的情况下工作,更新了 awnser

【讨论】:

  • 我不确定,这个修改给了我一个AttributeError: 'bytes' object has no attribute 'raw' 用于您的 sn-p 中的最后一个代码行。
  • 谢谢,这只是一个错字,现在我发现了。但是函数调用仍然会触发分段错误。 :\
  • 我是否必须明确设置argtypes,就像在这个问题中一样? stackoverflow.com/questions/27127413/…
  • 感谢您的更新,我尝试将其与 lemmatizer.py 集成,如果这对我有用。
  • 我能够使用您的新代码进入 C 函数,但当然正如输出 ([ERROR] Language file for lemmatizer has to be loaded first!) 所示,我必须处理 C 代码错误。
猜你喜欢
  • 2015-06-09
  • 1970-01-01
  • 2017-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-16
  • 1970-01-01
相关资源
最近更新 更多