我试图将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
答案 0 :(得分:0)
第一步,根据名称和部分来判断你的这个&#34; re2&#34;库(这是如此着名我不知道它;虽然它在Debian中,似乎没有任何需要它)是一个正则表达式库。你已经在Python的re
模块中拥有了一个非常灵活的模块。
其次,ctypes
是本机库的不安全接口;你需要完全正确地完成所有事情,这意味着要理解底层类型系统,包括可以分配或释放内存的时间以及通过哪些例程。它的正常用例是包装具有C接口的库而不编写任何非Python代码。在这种情况下,内存分配应该很容易,因为你只是返回一个bool并且不保留字符串引用。
但最重要的是,C ++ std::string根本就不是你所描述的char*
(事实上,C没有字符串数据类型!)。在C ++中,用于允许函数重载的基于类型的名称修改会使这一点变得明显,因为你没有找到bool there(char*)
函数,但是使用extern "C"
你使用C&C的链接来获取确切地说;并且ctypes
从包装器中获取所有类型信息。你可以通过从char指针构造一个字符串来修复你的there()
包装器(虽然你也应该传递长度,因为Python字符串可能包含nul),但是这个练习似乎是一种让事情变得更难的迂回方式。
考虑到你的方法需要C和Python包装器,没有编译器来键入检查组合,使用swig之类的东西可能会更好。