Python ctypes给出分段错误

Posted

技术标签:

【中文标题】Python ctypes给出分段错误【英文标题】:Python ctypes giving segmentation fault 【发布时间】:2014-09-16 06:47:14 【问题描述】:

我试图将 ctypes 用于著名的 re2 库。但我遇到了分段错误。

这是代码

tryone.cpp

#include <re2/re2.h>
#include <iostream>
#include <tuple>

using namespace re2;

RE2 re("([^ @]+)@([^ @]+)");

std::pair<string, string> match(string rawtext)
    string uname;
    string domain;
    RE2::PartialMatch(rawtext, re, &uname, &domain);
    return std::make_pair(uname, domain);


bool isit(string rawtext)
    return RE2::PartialMatch(rawtext, re);


extern "C" 
    bool there(string rawtext) return isit(rawtext); 


int  main() 
    if(isit("zbcd@xyz.com"))
    printf("PASS\n");
    

然后我用g++编译

g++ -I/usr/local/include -L/usr/local/lib -c -fPIC -std=c++11 tryone.cpp -lre2 -pthread -o tryone.o
g++ -shared -Wl,-soname,libmatch.so -L/usr/local/lib -lre2 -o libmatch.so  tryone.o /usr/local/lib/libre2.so.0

这是我的 python 包装函数

from ctypes import cdll, c_char_p, c_bool
lib = cdll.LoadLibrary('./libmatch.so')

lib.there.argtypes = [c_char_p]
lib.there.restype = c_bool

print lib.there("abcd@xyz.com")

但是当我运行 python 代码时,它给了我分段错误 python wrapper.py

【问题讨论】:

【参考方案1】:

第一步,从名称和你称之为“re2”库的部分来看(它是如此有名,我不知道它;虽然它在 Debian 中,但似乎没有什么需要它)是一个正则表达式库。您已经在 Python 的 re 模块中拥有了一个相当灵活的模块。

其次,ctypes 是原生库的不安全接口;您需要完全正确地完成所有工作,这意味着了解底层类型系统,包括诸如何时可以分配或释放内存以及由哪些例程进行的操作。它的正常用例是包装具有 C 接口的库,而无需编写任何非 Python 代码。在这种情况下,内存分配应该很容易,因为您只是返回一个布尔值而不是保留字符串引用。

但最重要的是,C++ std::string 根本不是您所描述的 char*(事实上,C 没有字符串数据类型!)。在 C++ 中,用于允许函数重载的基于类型的名称修改会很明显,因为您不会找到 bool there(char*) 函数,但使用 extern "C" 您使用 C 的链接,它完全采用名称; ctypes 从您的包装器中获取其所有类型信息。您可以通过从 char 指针构造一个字符串来修复您的 there() 包装器(尽管您也应该传递长度,因为 Python 字符串可能包含 nul),但这个练习似乎是一种让事情变得更难的迂回方法。

考虑到您的方法需要一个 C 和一个 Python 包装器,并且没有编译器来对组合进行类型检查,因此使用 swig 之类的东西可能会更好。

【讨论】:

以上是关于Python ctypes给出分段错误的主要内容,如果未能解决你的问题,请参考以下文章

在 Python ctypes 中加载共享库期间出现分段错误(核心转储)

尝试在 libc 上使用 ctypes 调用 environ 时,为啥 Python 会出现段错误?

Python Ctypes,C++ 字符串到浮点数的转换在 python 中调用 Matplotlib 后给出错误/舍入的结果

为啥写作主要;在 C 中给出一个段错误

正确编译的代码(没有错误)给出分段错误核心转储

python跟踪分段错误