swigサンプル
swigのサンプル。
- typemap(in) char * + int lenの引数をStringとして扱う
- typemap(ignore)とtypemap(argout) 出力用のポインタを返り値で返す(複数あったらtupleにつめる)
- numpyのarray入出力
- downcast
など
example.h
#include <string> #include <array> class String { std::string m_buf; public: void setChar(const char *s); void setCharWithLen(const char *s, int len); void setString(const std::string &s); void getCharWithLen(char *s, int len)const; }; class WString { std::wstring m_buf; public: void setChar(const wchar_t *s); void setCharWithLen(const wchar_t *s, int len); void setString(const std::wstring &s); void getCharWithLen(wchar_t *s, int len)const; }; class Matrix { std::array<float, 16> m_buf; public: void set(const float *p, int len); void get(float *p, int len)const; }; struct Vector3 { float x; float y; float z; Vector3(); ~Vector3(); }; class Shape { public: virtual ~Shape(){} virtual void getAABB(Vector3 &min, Vector3 &max)=0; }; class Box : public Shape { Vector3 m_origin; float w; float h; float d; public: Box(); ~Box(); void getAABB(Vector3 &min, Vector3 &max); }; Box *create_box_shape(float w, float h, float d);
example.cpp
#include "example.h" #include <fstream> // std::coutだとクラッシュしたのでとりあえず std::ofstream cout("example.log"); void String::setChar(const char *s) { m_buf=s; } void String::setCharWithLen(const char *s, int len) { m_buf.assign(s, s+len); } void String::setString(const std::string &s) { m_buf=s; } void String::getCharWithLen(char *s, int len)const { int i=0; for(auto it=m_buf.begin(); it!=m_buf.end() && i<len; ++it, ++i){ s[i]=*it; } for(; i<len; ++i){ s[i]=0; } } void WString::setChar(const wchar_t *s) { m_buf=s; } void WString::setCharWithLen(const wchar_t *s, int len) { m_buf.assign(s, s+len); } void WString::setString(const std::wstring &s) { m_buf=s; } void WString::getCharWithLen(wchar_t *s, int len)const { int i=0; for(auto it=m_buf.begin(); it!=m_buf.end() && i<len; ++it, ++i){ s[i]=*it; } for(; i<len; ++i){ s[i]=0; } } void Matrix::set(const float *p, int len) { std::copy(p, p+len, m_buf.begin()); } void Matrix::get(float *p, int len)const { std::copy(m_buf.begin(), m_buf.end(), p); } Vector3::Vector3() { cout << "Vector3::Vector3" << std::endl; } Vector3::~Vector3() { cout << "Vector3::~Vector3" << std::endl; } Box::Box() { cout << "Box::Box" << std::endl; } Box::~Box() { cout << "Box::~Box" << std::endl; } void Box::getAABB(Vector3 &min, Vector3 &max) { min=m_origin; min.x-=w; min.y-=h; min.z-=d; max=m_origin; max.x+=w; max.y+=h; max.z+=d; }; Box *create_box_shape(float w, float h, float d) { cout << "create_box_shape" << std::endl; return new Box; }
example.i
%module example %{ #include "example.h" %} ////////////////////////////////////////////////////////////////////////////// // setup numpy ////////////////////////////////////////////////////////////////////////////// %{ #define SWIG_FILE_WITH_INIT %} %include "numpy.i" %init %{ import_array(); %} %apply (float* IN_ARRAY1, int DIM1) {(const float *p, int len)}; %apply (float* ARGOUT_ARRAY1, int DIM1) {(float *p, int len)}; ////////////////////////////////////////////////////////////////////////////// // typemaps ////////////////////////////////////////////////////////////////////////////// #ifdef SWIGPYTHON // for setCharWithLen %typemap(in) (const char *s, int len){ if (PyString_Check($input)) { $1=PyString_AsString($input); $2=PyString_Size($input); } else { PyErr_SetString(PyExc_TypeError,"not a string"); return NULL; } } // for getCharWithLen %typemap(ignore) (char *s, int len)(char tmpbuf[1024]) { $1=tmpbuf; $2=1024; } %typemap(argout) (char *s, int len) { PyObject *o = $1[$2-1]=='\0' ? PyString_FromStringAndSize($1, strlen($1)) : PyString_FromStringAndSize($1, $2) ; if ((!$result) || ($result == Py_None)) { // 単独の返り値 $result = o; } else { // 既存のtupple返り値に値を連結する PyObject *o3 = PyTuple_New(1); PyTuple_SetItem(o3,0,o); if (!PyTuple_Check($result)) { // tuple PyObject *tmp = $result; $result = PyTuple_New(1); PyTuple_SetItem($result, 0, tmp); } PyObject *o2 = $result; $result = PySequence_Concat(o2,o3); Py_DECREF(o2); Py_DECREF(o3); } } // for setCharWithLen %typemap(in) (const wchar_t *s, int len){ if (PyUnicode_Check($input)) { $1=PyUnicode_AsUnicode($input); $2=PyUnicode_GET_SIZE($input); } else { PyErr_SetString(PyExc_TypeError,"not a unicode"); return NULL; } } // for setChar %typemap(in) const wchar_t *s { if (PyUnicode_Check($input)) { $1=PyUnicode_AsUnicode($input); } else { PyErr_SetString(PyExc_TypeError,"not a unicode"); return NULL; } } // for getCharWithLen %typemap(ignore) (wchar_t *s, int len)(wchar_t tmpbuf[1024]) { $1=tmpbuf; $2=1024; } %typemap(argout) (wchar_t *s, int len) { PyObject *o = $1[$2-1]=='\0' ? PyUnicode_FromUnicode($1, wcslen($1)) : PyUnicode_FromUnicode($1, $2) ; if ((!$result) || ($result == Py_None)) { // 単独の返り値 $result = o; } else if(PyTuple_Check($result)){ // 既存のtuple返り値と連結 PyObject *o2 = $result; PyObject *o3 = PyTuple_New(1); PyTuple_SetItem(o3,0,o); $result = PySequence_Concat(o2,o3); Py_DECREF(o2); Py_DECREF(o3); } else{ // 非tuple返り値と連結 PyObject *o2=$result; $result=PyTuple_New(2); PyTuple_SetItem($result, 0, o2); PyTuple_SetItem($result, 1, o); } } // for getAABB %typemap(ignore) (Vector3 &min, Vector3 &max)(Vector3 tmpmin, Vector3 tmpmax) { $1=&tmpmin; $2=&tmpmax; } %typemap(argout) (Vector3 &min, Vector3 &max) { Vector3 *v1=new Vector3; *v1=*$1; Vector3 *v2=new Vector3; *v2=*$2; if ((!$result) || ($result == Py_None)) { // 単独の返り値 $result = PyTuple_New(2); PyTuple_SetItem($result, 0, SWIG_NewPointerObj(v1, $1_descriptor, 1)); PyTuple_SetItem($result, 1, SWIG_NewPointerObj(v2, $2_descriptor, 1)); } else if(PyTuple_Check($result)){ // tuple連結 PyObject *o1 = $result; PyObject *o2 = PyTuple_New(2); PyTuple_SetItem(o2, 0, SWIG_NewPointerObj(v1, $1_descriptor, 1)); PyTuple_SetItem(o2, 1, SWIG_NewPointerObj(v2, $2_descriptor, 1)); $result = PySequence_Concat(o1, o2); Py_DECREF(o1); Py_DECREF(o2); } else{ // 3tuple PyObject *o=$result; $result = PyTuple_New(3); PyTuple_SetItem($result, 0, o); PyTuple_SetItem($result, 1, SWIG_NewPointerObj(v1, $1_descriptor, 1)); PyTuple_SetItem($result, 2, SWIG_NewPointerObj(v2, $2_descriptor, 1)); } } ////////////////////////////////////////////////////////////////////// #endif %newobject create_box_shape; %include example.h ////////////////////////////////////////////////////////////////////// // extend ////////////////////////////////////////////////////////////////////// %extend Box { static Box* downcast(Shape* s){ return (Box*)s; } };
setup.py
#!/usr/bin/env python """ libexample """ MODULE_NAME='example' PY_MODULE_DIR='build/lib.win32-2.7/'+MODULE_NAME import os from distutils.core import setup, Extension from distutils.dir_util import mkpath mkpath(PY_MODULE_DIR) include_dirs=[ '/Python27/Lib/site-packages/numpy/core/include', ] ext= Extension(MODULE_NAME+'.___init__', sources=['example.i', 'example.cpp'], swig_opts=['-I'+d for d in include_dirs]+[ '-module', '__init__', '-outdir', PY_MODULE_DIR, '-c++', '-fastdispatch', '-DSWIG_TYPE_TABLE='+MODULE_NAME, ], include_dirs=include_dirs, extra_compile_args=[ '-Wno-unused-parameter', '-Wno-unused-but-set-variable', '-std=c++0x', ], define_macros=[ ], library_dirs=[], libraries=[] ) setup (name = MODULE_NAME, version = '0.1', author = "ousttrue", description = """simple opengl utility""", ext_modules = [ext], py_modules = [MODULE_NAME], )
使用例
#!/usr/bin/env python import example import numpy # string s=example.String() s.setChar("hoge") print type(s.getCharWithLen()) print s.getCharWithLen() s.setCharWithLen("fuga") print type(s.getCharWithLen()) print s.getCharWithLen() # wstring w=example.WString() w.setChar(u"hoge") print type(w.getCharWithLen()) print w.getCharWithLen() w.setCharWithLen(u"fuga") print type(w.getCharWithLen()) print w.getCharWithLen() # numpy.array m=example.Matrix() data=numpy.array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ], 'f') print type(data) print data m.set(data) print type(m.get(16)) print m.get(16) #b=example.Box() # shape b=example.create_box_shape(1, 2, 3) s=example.Box.downcast(b) print s aabbMin, aabbMax=s.getAABB() print aabbMin, aabbMax