2015-05-27 3 views
3

У меня есть две шаблоны с swig с кучей дубликата кода в них. Я хотел бы, чтобы закрепить код следующим образом:Как я могу повторно использовать код через шаблоны типов swig?

%{ 
    #include "structure_defs.h" 
%} 

%ignore Cartesian2PyList(const schrodinger::Cartesian&); 
PyObject* Cartesian2PyList(const schrodinger::Cartesian& cartesian) 
{ 
    PyObject *o; 
    o = PyList_New(3); 
    PyObject* item = PyFloat_FromDouble(cartesian.x); 
    PyList_SetItem(o, 0, item); 
    item = PyFloat_FromDouble(cartesian.y); 
    PyList_SetItem(o, 1, item); 
    item = PyFloat_FromDouble(cartesian.z); 
    PyList_SetItem(o, 2, item); 
    return o; 
} 

%typemap(out) schrodinger::Cartesian 
{ 
    $result = Cartesian2PyList($1); 
} 
%typemap(out) std::vector<schrodinger::Cartesian> 
{ 
    PyObject *o; 
    o = PyList_New($1.size()); 
    for (uint i=0; i<$1.size(); i++) { 
    PyObject *elem = Cartesian2PyList($1.at(i)); 
    PyList_SetItem(o, i, elem); 
    } 
    $result = o; 
} 

%include "cartesian.h" 

Однако это не удается скомпилировать, потому что определение Cartesian2PyList не может быть найдено во время компиляции. Каков наилучший способ повторного использования кода в нескольких типах?

ответ

2

Вы можете передать код прямо в сгенерированный файл .c, используя %{ %}. Простейший способ повторного использования кода внутри оболочки - это просто поместить его внутри, возможно, как статическую функцию, чтобы она не столкнулась ни с чем другим в том же модуле. В вашем примере это будет работать:

%{ 
    #include "structure_defs.h" 
%} 

%{ 
static PyObject* Cartesian2PyList(const schrodinger::Cartesian& cartesian) 
{ 
    PyObject *o; 
    o = PyList_New(3); 
    PyObject* item = PyFloat_FromDouble(cartesian.x); 
    PyList_SetItem(o, 0, item); 
    item = PyFloat_FromDouble(cartesian.y); 
    PyList_SetItem(o, 1, item); 
    item = PyFloat_FromDouble(cartesian.z); 
    PyList_SetItem(o, 2, item); 
    return o; 
} 
%} 

%typemap(out) schrodinger::Cartesian 
{ 
    $result = Cartesian2PyList($1); 
} 
%typemap(out) std::vector<schrodinger::Cartesian> 
{ 
    PyObject *o; 
    o = PyList_New($1.size()); 
    for (uint i=0; i<$1.size(); i++) { 
    PyObject *elem = Cartesian2PyList($1.at(i)); 
    PyList_SetItem(o, i, elem); 
    } 
    $result = o; 
} 

%include "cartesian.h" 

Вы могли бы объединить два %{ %} блоков в единый блок здесь, если вы так хотели.

Я также удалил директиву %ignore там, потому что код внутри %{ %} просто выводится в сгенерированный модуль, а не завернут, поэтому будет избыточным. На otherhand, если вы действительно хотите, чтобы он обернут, а также определено в сгенерированном коде можно использовать %inline %{ ... %}, например:

%inline %{ 
static PyObject* Cartesian2PyList(const schrodinger::Cartesian& cartesian) 
{ 
    //... 
} 
%} 

Есть умные вещи, которые вы можете использовать, если вы пишете более общий код SWIG а не только один модуль, см. fragments, %define и $typemap. В простом случае достаточно просто написать код для использования внутри модуля, как показано выше.

Смежные вопросы