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