SWIG
cоздание мультиязыковых интерфейсов
для C/C++ библиотек
Why
High level (Python, Ruby, Java, C#, Go, … )
● Высокая скорость разработки (программы для людей)
o Быстрое создание про...
Survey
Extending and Embedding
Dynamic and Static
Python -- библиотека для компиляции и интерпретации
байт-кода написанная...
Survey
● Python C API
● Ctypes
● Boost.Python
● Cython (pyrex)
● RPython
● SWIG
● Shiboken (PySide)
● SIP (PyQt)
Survey
● Python C API
● Ctypes
● Boost.Python
● Cython (pyrex)
● RPython
● SWIG
● Shiboken (PySide)
● SIP (PyQt)
Python C API (пример)
Враппер над двумя функциями
char *readline(const char *);int
add_history(const char *);
Python C API (пример)
#include <Python.h>#include <readline/readline.h>
PyObject *
fn_readline(PyObject *self, PyObject *a...
Python C API (пример)
PyObject *
fn_add_history(PyObject *self, PyObject *args){
char *line;
int status;
PyObject *o;
if (...
Python C API (пример)
Py_INCREF(Py_None); return Py_None;
Python C API (пример)
static PyMethodDef
methods[] = {
{"readline", fn_readline, METH_VARARGS, NULL},
{"add_history", fn_a...
Python C API (пример)
PyMODINIT_FUNC PyInit_spam(void)
{
return PyModule_Create(&spammodule);
}
PyMODINIT_FUNC initspam(vo...
Python C API (use)
Python C API (use)
gcc -dynamiclib -I/usr/include/python2.5 -lpython -lreadline mod_readline.c
-o readline.so
Use setup.py...
Python C API (conclusion)
● Самая тесная интеграция с Python из всех
возможных
● Лучшая производительность
● Нужно все вре...
Python C API (conclusion)
● Несложный в понимании и изучении для
людей с C-background
● Хорошо документирован
● Объемный
●...
Survey
● Python C API
● Ctypes
● Boost.Python
● Cython (pyrex)
● RPython
● SWIG
Boost.Python (keynotes)
● Позволяет небольшими усилиями экспортировать
типы из C++ в Python
● Без сторонних утилит, только...
Boost.Python (keynotes)
● Надежная устоявшаяся библиотека (в
boost фигню не берут)
● Обновляется не часто (последний комми...
Boost.Python (projects)
Их много, например …
● Civilization IV
● OpenSceneGraph Bindings
● PythonMagick
● Fusion (часть Tw...
Boost.Python (code)
char const* greet(){
return "hello, world";}
>>> import hello_ext>>>
print hello_ext.greet()
hello, wo...
Boost.Python (code)
class_<World>("World", init<std::string>())
.def(init<double, double>())
.def("greet", &World::greet)
...
Boost.Python (features)
● Constructors
● Class Properties
● Inheritance
● Class Virtual Functions
● Virtual Functions with...
Boost.Python (features, version 2)
● References and Pointers
● Globally Registered Type Coercions
● Automatic Cross-Module...
Boost.Python (C++)
● Это modern С++, детка
● Потенциально медленная
компиляция
● Потонциально сложный для
отладки и анализ...
Boost.Python (conclusion)
Отличная библиотека, если не боитесь C++
Survey
● Python C API
● Ctypes
● Boost.Python
● Cython (pyrex)
● RPython
● SWIG
Survey
● Python C API
● Ctypes
● Boost.Python
● Cython (pyrex)
● RPython
● SWIG
RPython
● Язык реализации PyPy
● Restricted Python
o Возможность статического вывода типов
o Types are inferred, not state...
Survey
● Python C API
● Ctypes
● Boost.Python
● Cython (pyrex)
● RPython
● SWIG
SWIG
● User story -- мультиплатформенная бизнес логика
● Simplified Wrapper and Interface Generator
● Проект развивался с ...
SWIG (langs)
Allegro CL
C#
CFFI
CLISP
Chicken
D
Go
Guile
Java
Javascript
UFFI
Lua
Modula-3
Mzscheme
OCAML
Octave
Perl
PHP
...
SWIG (projects)
● Subversion
● PyOgre
● PyOpenGL
● wxPython
● XML::Xerces
● OpenCV
● Crystal Space 3D
● … (много других)
example.c
example.h
example.c
example.h
example.i
example.c
example.h
example_wrap.c
example.py
example.i
SWIG
example.c
example.h
example_wrap.c
example.py
example.i python setup.by build
_example.so (pyd)
example.c
example.h
example_wrap.c
example.py
example.i pip install -e .
_example.so (pyd)
module example
SWIG (example)
/* File : example.c *//* A global variable */double Foo = 3.0;/* Compute
the greatest common divisor of pos...
SWIG (example)
/* File : example.i */%module example%inline %{
extern int gcd(int x, int y);
extern double Foo;%}
SWIG (example)
example_wrap.c
около 4000 строк кода
#ifdef __cplusplus
extern "C" {#endif
SWIGINTERN PyObject *_wrap_gcd(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyO...
#ifdef __cplusplus
extern "C" {#endif
SWIGINTERN PyObject *_wrap_gcd(PyObject *SWIGUNUSEDPARM(self),
PyObject *args) {
PyO...
if (!PyArg_ParseTuple(args,(char *)"OO:gcd",&obj0,&obj1)) SWIG_fail;
ecode1 = SWIG_AsVal_int(obj0, &val1);
if (!SWIG_IsOK(...
result = (int)gcd(arg1,arg2);
resultobj = SWIG_From_int(static_cast< int >(result));
return resultobj;
fail:
return NULL;
}
SWIG (example)
example.py
80 строк кода
SWIG (example)
# file: runme.pyimport example # Call our gcd() function
x = 42
y = 105
g = example.gcd(x,y)print "The gcd ...
SWIG (interface file)
● Принцип отделения от оригинального *.h файла
● C, С++ препроцессор и парсер (include по
умолчанию ...
SWIG (interface file)
● Принцип отделения от оригинального *.h файла
● C, С++ препроцессор и парсер (include по
умолчанию ...
SWIG (cases)
● Работает очень прозрачно, без магии
● Basic Type Handling
o integers
o char -- строка
o bool -- int или boo...
SWIG (cases)
● Simple pointers
o непрозрачные сущности
o храняться void* и type-tag (проверка типов на
границах)
o Разымен...
SWIG (cases)
● Simple pointers
disown() — снять флаг владения
acquire() — установить флаг владения
own() — проверка владен...
SWIG (cases)
%module fileioFILE *fopen(char *, char *);int fclose(FILE *);unsigned
fread(void *ptr, unsigned size, unsigne...
SWIG (cases)
# Copy a file def filecopy(source,target):
f1 = fopen(source,"r")
f2 = fopen(target,"w")
buffer = malloc(8192...
SWIG (cases)
● Derived types, structs, and classes
Everything else is a
pointer
Даже Undefined data types
+ Proxy
SWIG (cases)
struct Vector {
double x,y,z;
}
SWIG (cases)
struct Vector {
double x,y,z;
}
SWIG (cases)
double Vector_x_get(struct Vector *obj) {
return obj->x;}double Vector_y_get(struct Vector *obj) {
return obj...
SWIG (cases)
struct Vector *new_Vector() {
return (Vector *) calloc(1,sizeof(struct
Vector));}void delete_Vector(struct Ve...
SWIG (cases)
v = new_Vector()
Vector_x_set(v,2)
Vector_y_set(v,10)
Vector_z_set(v,-5)...
delete_Vector(v)
SWIG (cases)
class Vector(_object):
__swig_setmethods__ = {}
__setattr__ = lambda self, name, value: _swig_setattr(self, V...
SWIG (cunclusion)
● Написан на C, C++
● Без зависимостей (для запуска нужен один .exe), не
нужны целевые языки
● Доступен ...
SWIG (cunclusion)
● Много языков (интересен универсальностью)
● Очень желательно понимать C/C++
● Не навязывает мораль (ра...
SWIG (cunclusion)
Может оказаться очень полезным
элементом архитектуры
Спасибо за внимание!
aleksei.cherkes@gmail.com
https://www.facebook.com/aleksei.cherkes
Upcoming SlideShare
Loading in …5
×

SWIG — cоздание мультиязыковых интерфейсов для C/C++ библиотек

1,222 views

Published on

"SWIG — cоздание мультиязыковых интерфейсов для C/C++ библиотек", Алексей Черкес

Кратко рассказано о том, что такое биндинг и Pуthon c API. Краткий обзор средств биндинга для Python. SWIG: что такое, зачем нужен, особенности, схема работы утилит, порядок запуска и сборки, принципы работы, как происходит сопоставление объектных моделей С++ и целевого языка. Примеры на Python и C#. Опыт применения, плюсы/минусы.

Published in: Technology
1 Comment
0 Likes
Statistics
Notes
  • Be the first to like this

No Downloads
Views
Total views
1,222
On SlideShare
0
From Embeds
0
Number of Embeds
15
Actions
Shares
0
Downloads
7
Comments
1
Likes
0
Embeds 0
No embeds

No notes for slide

SWIG — cоздание мультиязыковых интерфейсов для C/C++ библиотек

  1. 1. SWIG cоздание мультиязыковых интерфейсов для C/C++ библиотек
  2. 2. Why High level (Python, Ruby, Java, C#, Go, … ) ● Высокая скорость разработки (программы для людей) o Быстрое создание прототипов o Рефакторинг o Легче делать UI, сетевое взаимодействие и т.п o REPL ● Легко кастомизируется, конфигурируется и перенастраивается Low level (С, С++ ?) ● Высокая скорость исполнения (программы для компьютеров) ● Доступ к системным компонентам (OpenGL, DirectX и т.п) ● Портируемость на уровне исходных кодов ● Огромное количество существующего и создаваемого кода (даже на чистом C) o libgit (C89) o libvirt o systemd o CPython! ● Debug cycle (compile, run, attach, debug …)
  3. 3. Survey Extending and Embedding Dynamic and Static Python -- библиотека для компиляции и интерпретации байт-кода написанная на C Явный поиск и загрузка dll, so. Интроспекция бинарных объектов.
  4. 4. Survey ● Python C API ● Ctypes ● Boost.Python ● Cython (pyrex) ● RPython ● SWIG ● Shiboken (PySide) ● SIP (PyQt)
  5. 5. Survey ● Python C API ● Ctypes ● Boost.Python ● Cython (pyrex) ● RPython ● SWIG ● Shiboken (PySide) ● SIP (PyQt)
  6. 6. Python C API (пример) Враппер над двумя функциями char *readline(const char *);int add_history(const char *);
  7. 7. Python C API (пример) #include <Python.h>#include <readline/readline.h> PyObject * fn_readline(PyObject *self, PyObject *args){ char *prompt; char *line; PyObject *o; if (!PyArg_ParseTuple(args, “s”, &prompt)) return NULL; line = readline(prompt); o = Py_BuildValue(“s”, line); free(line); return o;}
  8. 8. Python C API (пример) PyObject * fn_add_history(PyObject *self, PyObject *args){ char *line; int status; PyObject *o; if (!PyArg_ParseTuple(args, "s", &line)) return NULL; status = add_history(line); o = Py_BuildValue("i", status); return o;}
  9. 9. Python C API (пример) Py_INCREF(Py_None); return Py_None;
  10. 10. Python C API (пример) static PyMethodDef methods[] = { {"readline", fn_readline, METH_VARARGS, NULL}, {"add_history", fn_add_history, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL}}; PyMODINIT_FUNC initreadline(void){ (void) Py_InitModule("readline", methods);}
  11. 11. Python C API (пример) PyMODINIT_FUNC PyInit_spam(void) { return PyModule_Create(&spammodule); } PyMODINIT_FUNC initspam(void) { (void) Py_InitModule("spam", SpamMethods); }
  12. 12. Python C API (use)
  13. 13. Python C API (use) gcc -dynamiclib -I/usr/include/python2.5 -lpython -lreadline mod_readline.c -o readline.so Use setup.py instead
  14. 14. Python C API (conclusion) ● Самая тесная интеграция с Python из всех возможных ● Лучшая производительность ● Нужно все время считать ссылки ● Нужно хорошо знать C
  15. 15. Python C API (conclusion) ● Несложный в понимании и изучении для людей с C-background ● Хорошо документирован ● Объемный ● Опасно использовать не понимая ● Что если функций не 2 а 200?
  16. 16. Survey ● Python C API ● Ctypes ● Boost.Python ● Cython (pyrex) ● RPython ● SWIG
  17. 17. Boost.Python (keynotes) ● Позволяет небольшими усилиями экспортировать типы из C++ в Python ● Без сторонних утилит, только С++ компилятор ● None intrusive wrapping (подходит для оборачивания сторонних библиотек без изменения их кода) ● Extensions and embedding
  18. 18. Boost.Python (keynotes) ● Надежная устоявшаяся библиотека (в boost фигню не берут) ● Обновляется не часто (последний коммит осень 2013, минорная поддержка) ● Python 3 есть ● Много successful stories...
  19. 19. Boost.Python (projects) Их много, например … ● Civilization IV ● OpenSceneGraph Bindings ● PythonMagick ● Fusion (часть Twisted)
  20. 20. Boost.Python (code) char const* greet(){ return "hello, world";} >>> import hello_ext>>> print hello_ext.greet() hello, world #include <boost/python.hpp> BOOST_PYTHON_MODULE(hello_ext){ using namespace boost::python; def("greet", greet);}
  21. 21. Boost.Python (code) class_<World>("World", init<std::string>()) .def(init<double, double>()) .def("greet", &World::greet) .def("set", &World::set); struct World{ World(std::string msg): msg(msg) {} // added constructor void set(std::string msg) { this->msg = msg; } std::string greet() { return msg; } std::string msg;};
  22. 22. Boost.Python (features) ● Constructors ● Class Properties ● Inheritance ● Class Virtual Functions ● Virtual Functions with Default Implementations
  23. 23. Boost.Python (features, version 2) ● References and Pointers ● Globally Registered Type Coercions ● Automatic Cross-Module Type Conversions ● Efficient Function Overloading ● C++ to Python Exception Translation ● Default Arguments ● Keyword Arguments ● Manipulating Python objects in C++ ● Exporting C++ Iterators as Python Iterators ● Documentation Strings
  24. 24. Boost.Python (C++) ● Это modern С++, детка ● Потенциально медленная компиляция ● Потонциально сложный для отладки и анализа код ● Ошибки инстанцирования шаблонов ● Не header-only библиотека
  25. 25. Boost.Python (conclusion) Отличная библиотека, если не боитесь C++
  26. 26. Survey ● Python C API ● Ctypes ● Boost.Python ● Cython (pyrex) ● RPython ● SWIG
  27. 27. Survey ● Python C API ● Ctypes ● Boost.Python ● Cython (pyrex) ● RPython ● SWIG
  28. 28. RPython ● Язык реализации PyPy ● Restricted Python o Возможность статического вывода типов o Types are inferred, not stated explicitly o All that analysis happens on a whole-program basis! ● Трансформируется в C => компилируется ● RPython is not Python
  29. 29. Survey ● Python C API ● Ctypes ● Boost.Python ● Cython (pyrex) ● RPython ● SWIG
  30. 30. SWIG ● User story -- мультиплатформенная бизнес логика ● Simplified Wrapper and Interface Generator ● Проект развивался с 1995 ● Зародился в университетских кругах ● Постоянно обновлятся, версии выходят часто (последняя 2014.05.27) ● GPL license -- на SWIG, что хотите -- на сгенерированный код
  31. 31. SWIG (langs) Allegro CL C# CFFI CLISP Chicken D Go Guile Java Javascript UFFI Lua Modula-3 Mzscheme OCAML Octave Perl PHP Python R Ruby Tcl
  32. 32. SWIG (projects) ● Subversion ● PyOgre ● PyOpenGL ● wxPython ● XML::Xerces ● OpenCV ● Crystal Space 3D ● … (много других)
  33. 33. example.c example.h
  34. 34. example.c example.h example.i
  35. 35. example.c example.h example_wrap.c example.py example.i SWIG
  36. 36. example.c example.h example_wrap.c example.py example.i python setup.by build _example.so (pyd)
  37. 37. example.c example.h example_wrap.c example.py example.i pip install -e . _example.so (pyd) module example
  38. 38. SWIG (example) /* File : example.c *//* A global variable */double Foo = 3.0;/* Compute the greatest common divisor of positive integers */int gcd(int x, int y) { int g; g = y; while (x > 0) { g = x; x = y % x; y = g; } return g;}
  39. 39. SWIG (example) /* File : example.i */%module example%inline %{ extern int gcd(int x, int y); extern double Foo;%}
  40. 40. SWIG (example) example_wrap.c около 4000 строк кода
  41. 41. #ifdef __cplusplus extern "C" {#endif SWIGINTERN PyObject *_wrap_gcd(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; int arg1 ; int arg2 ; int val1 ; int ecode1 = 0 ; int val2 ; int ecode2 = 0 ; PyObject * obj0 = 0 ; PyObject * obj1 = 0 ; int result; if (!PyArg_ParseTuple(args,(char *)"OO:gcd",&obj0,&obj1)) SWIG_fail; ecode1 = SWIG_AsVal_int(obj0, &val1); if (!SWIG_IsOK(ecode1)) { SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "gcd" "', argument " "1"" of type '" "int""'"); } arg1 = static_cast< int >(val1); ecode2 = SWIG_AsVal_int(obj1, &val2); if (!SWIG_IsOK(ecode2)) { SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "gcd" "', argument " "2"" of type '" "int""'"); } arg2 = static_cast< int >(val2); result = (int)gcd(arg1,arg2); resultobj = SWIG_From_int(static_cast< int >(result)); return resultobj; fail: return NULL;}
  42. 42. #ifdef __cplusplus extern "C" {#endif SWIGINTERN PyObject *_wrap_gcd(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; int arg1 ; int arg2 ; int val1 ; int ecode1 = 0 ; int val2 ; int ecode2 = 0 ; PyObject * obj0 = 0 ; PyObject * obj1 = 0 ; int result; ...}
  43. 43. if (!PyArg_ParseTuple(args,(char *)"OO:gcd",&obj0,&obj1)) SWIG_fail; ecode1 = SWIG_AsVal_int(obj0, &val1); if (!SWIG_IsOK(ecode1)) { SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "gcd" "', argument " "1"" of type '" "int""'"); } arg1 = static_cast< int >(val1);
  44. 44. result = (int)gcd(arg1,arg2); resultobj = SWIG_From_int(static_cast< int >(result)); return resultobj; fail: return NULL; }
  45. 45. SWIG (example) example.py 80 строк кода
  46. 46. SWIG (example) # file: runme.pyimport example # Call our gcd() function x = 42 y = 105 g = example.gcd(x,y)print "The gcd of %d and %d is %d" % (x,y,g)# Manipulate the Foo global variable# Output its current valueprint "Foo = ", example.cvar.Foo# Change its value example.cvar.Foo = 3.1415926# See if the change took effectprint "Foo = ", example.cvar.Foo
  47. 47. SWIG (interface file) ● Принцип отделения от оригинального *.h файла ● C, С++ препроцессор и парсер (include по умолчанию выключены) ● % — начало всех SWIG директив ● %{ … }% -- копируется во wrap
  48. 48. SWIG (interface file) ● Принцип отделения от оригинального *.h файла ● C, С++ препроцессор и парсер (include по умолчанию выключены) ● % — начало всех SWIG директив ● %{ … }% -- копируется во wrap
  49. 49. SWIG (cases) ● Работает очень прозрачно, без магии ● Basic Type Handling o integers o char -- строка o bool -- int или bool, если есть
  50. 50. SWIG (cases) ● Simple pointers o непрозрачные сущности o храняться void* и type-tag (проверка типов на границах) o Разыменовать нельзя o Получить значение можно, но это бессмысленно; поменять значения нельзя
  51. 51. SWIG (cases) ● Simple pointers disown() — снять флаг владения acquire() — установить флаг владения own() — проверка владения (bool) next() append()
  52. 52. SWIG (cases) %module fileioFILE *fopen(char *, char *);int fclose(FILE *);unsigned fread(void *ptr, unsigned size, unsigned nobj, FILE *);unsigned fwrite(void *ptr, unsigned size, unsigned nobj, FILE *);void *malloc(int nbytes);void free(void *);
  53. 53. SWIG (cases) # Copy a file def filecopy(source,target): f1 = fopen(source,"r") f2 = fopen(target,"w") buffer = malloc(8192) nbytes = fread(buffer,8192,1,f1) while (nbytes > 0): fwrite(buffer,8192,1,f2) nbytes = fread(buffer,8192,1,f1) free(buffer)
  54. 54. SWIG (cases) ● Derived types, structs, and classes Everything else is a pointer Даже Undefined data types + Proxy
  55. 55. SWIG (cases) struct Vector { double x,y,z; }
  56. 56. SWIG (cases) struct Vector { double x,y,z; }
  57. 57. SWIG (cases) double Vector_x_get(struct Vector *obj) { return obj->x;}double Vector_y_get(struct Vector *obj) { return obj->y;}double Vector_z_get(struct Vector *obj) { return obj->z;}void Vector_x_set(struct Vector *obj, double value) { obj->x = value;}void Vector_y_set(struct Vector *obj, double value) { obj->y = value;}void Vector_z_set(struct Vector *obj, double value) { obj->z = value;}
  58. 58. SWIG (cases) struct Vector *new_Vector() { return (Vector *) calloc(1,sizeof(struct Vector));}void delete_Vector(struct Vector *obj) { free(obj);}
  59. 59. SWIG (cases) v = new_Vector() Vector_x_set(v,2) Vector_y_set(v,10) Vector_z_set(v,-5)... delete_Vector(v)
  60. 60. SWIG (cases) class Vector(_object): __swig_setmethods__ = {} __setattr__ = lambda self, name, value: _swig_setattr(self, Vector, name, value) __swig_getmethods__ = {} __getattr__ = lambda self, name: _swig_getattr(self, Vector, name) __repr__ = _swig_repr __swig_setmethods__["x"] = _example.Vector_x_set __swig_getmethods__["x"] = _example.Vector_x_get if _newclass:x = _swig_property(_example.Vector_x_get, _example.Vector_x_set) __swig_setmethods__["y"] = _example.Vector_y_set __swig_getmethods__["y"] = _example.Vector_y_get if _newclass:y = _swig_property(_example.Vector_y_get, _example.Vector_y_set) __swig_setmethods__["z"] = _example.Vector_z_set __swig_getmethods__["z"] = _example.Vector_z_get if _newclass:z = _swig_property(_example.Vector_z_get, _example.Vector_z_set) def __init__(self): this = _example.new_Vector() try: self.this.append(this) except: self.this = this __swig_destroy__ = _example.delete_Vector __del__ = lambda self : None; Vector_swigregister = _example.Vector_swigregister Vector_swigregister(Vector)
  61. 61. SWIG (cunclusion) ● Написан на C, C++ ● Без зависимостей (для запуска нужен один .exe), не нужны целевые языки ● Доступен на многих платформах ● Работает очень быстро ● Хорошая документация ● Хороший генерируемый код (можно разобраться) ● Кастомизируемый (можно модифицировать поведение генератора)
  62. 62. SWIG (cunclusion) ● Много языков (интересен универсальностью) ● Очень желательно понимать C/C++ ● Не навязывает мораль (разрешает отстрелить ногу) ● Но при этом кастомизируемый, гибкий ● Требует немного больше времени на изучение, чем Boost.Python, но начать с простого легко ● Хороший и прозрачный генерируемый код
  63. 63. SWIG (cunclusion) Может оказаться очень полезным элементом архитектуры
  64. 64. Спасибо за внимание! aleksei.cherkes@gmail.com https://www.facebook.com/aleksei.cherkes

×