2014-09-16 3 views
0

Я пытался использовать ctypes для знаменитой библиотеки re2. Но я получаю ошибку сегментации.Python ctypes, дающий ошибку сегментации

Вот код

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("[email protected]")){ 
    printf("PASS\n"); 
    } 
} 

Затем я составил с г ++

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 

Вот мой питон функция упаковщик

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("[email protected]") 

Но когда я бегу питон-треска e это дает мне ошибку сегментации python wrapper.py

ответ

0

Первый шаг, судя по имени и части, которую вы называете этой библиотекой «re2» (которая так известна, что я не знал об этом; пока он находится в Debian, ничто не требует этого) является библиотекой регулярных выражений. У вас уже есть довольно гибкий модуль Python re.

Во-вторых, ctypes - небезопасный интерфейс для родных библиотек; вам нужно получить все правильно, что означает понимание базовой системы типов, включая такие вещи, как когда память может быть выделена или освобождена и какие подпрограммы. Его нормальный вариант использования - это библиотеки обтекания, которые имеют C-интерфейсы без написания кода, отличного от Python. В этом случае распределение памяти должно быть простым, поскольку вы просто возвращаете bool и не сохраняете ссылку на строку.

Но самое главное, C++ std::string просто не является char*, как вы его описали (на самом деле C не имеет строкового типа данных!). В C++ тип, называемый изменением имени, используемый для разрешения перегрузки функций, сделал бы это очевидным, так как вы бы не нашли функцию bool there(char*), но с extern "C" вы используете ссылку C, которая точно принимает имя; и ctypes получает всю информацию своего типа от вашей обертки. Вы можете исправить свою there() оболочку, построив строку из указателя char (хотя вы также должны передавать длину, так как строки Python могут содержать nul), но это упражнение кажется крутым способом сделать вещи сложнее.

Учитывая, что ваш подход требует как C, так и оболочки Python, без компилятора для проверки проверки комбинации, вам может быть лучше, используя что-то вроде swig.

+0

Спасибо. Я новичок в C++. Ваш совет работал – digitaltracer