金子邦彦研究室プログラミングRuby による Web/データベース・プログラミングSwig を利用して、Ruby プログラムから C++ のテンプレートクラスを呼び出す

Swig を利用して、Ruby プログラムから C++ のテンプレートクラスを呼び出す

<要点>

関連する外部ページhttp://www.swig.org/Doc1.3/SWIGPlus.html

Swig を利用して、Ruby プログラムから C++ のテンプレートクラスを呼び出す例

  1. C++ プログラムの作成

    例えば、次のように triple.hpp を作成. C++ のテンプレートクラスでは,ヘッダファイルに,クラス定義を全て書くことに注意

    template<class T> class Triple {
    private:
      T _x;
      T _y;
      T _z;
    public:
      Triple() {};
      ~Triple() {};
      void set_x( const T& arg ) { this->_x = arg;  return; }; 
      void set_y( const T& arg ) { this->_y = arg;  return; };  
      void set_z( const T& arg ) { this->_z = arg;  return; };  
      T x() { return this->_x; }; 
      T y() { return this->_y; }; 
      T z() { return this->_z; }; 
    };
    
  2. triple.i の作成

    モジュール名を MyCPP に設定している.

    %module MyCPP
    %{
    #include "triple.hpp"
    %}
    %include "triple.hpp"
    %template(IntTriple) Triple<int>; 
    
  3. swig の実行
    rm -f triple_wrap.*
    swig2.0 -ruby -c++ triple.i 
    

    [image]
  4. extconf.rb の作成

    「create_makefile('MyCPP')」と記述しているので、MyCPP.so が生成されることになる

    require 'mkmf'
    
    dir_config('triple')
    $libs += " -lstdc++ "
    if have_header('triple.hpp') 
      create_makefile('MyCPP')
    end
    
  5. ビルド
    ruby extconf.rb
    make CC=g++
    

    [image]

    nm で確認してみる

    [image]
  6. インストール
    sudo make site-install
    

    [image]
  7. 使ってみる
    irb
    
    require 'MyCPP'
    a = MyCPP::IntTriple.new
    a.set_x(1)
    a.set_y(2)
    a.set_z(3)
    a.x
    a.y
    a.z 
    

    [image]

C++ のヘッダファイルで namespace を使っている場合

Swig では C++ のヘッダファイル内の namespace は無視される(その結果、競合が起きる場合のために競合を避けるための機能もあります)。

  1. C++ プログラムの作成

    例えば、次のように triple.hpp を作成. C++ のテンプレートクラスでは,ヘッダファイルに,クラス定義を全て書くことに注意

    
    namespace hoge {
      template<class T> class Triple {
      private:
        T _x;
        T _y;
        T _z;
      public:
        Triple() {};
        ~Triple() {};
        void set_x( const T& arg ) { this->_x = arg;  return; }; 
        void set_y( const T& arg ) { this->_y = arg;  return; };  
        void set_z( const T& arg ) { this->_z = arg;  return; };  
        T x() { return this->_x; }; 
        T y() { return this->_y; }; 
        T z() { return this->_z; }; 
      };
    }
    
  2. triple.i の作成

    モジュール名を MyCPP に設定している.

    %module MyCPP
    %{
    #include "triple.hpp"
    %}
    %include "triple.hpp"
    %template(IntTriple) hoge::Triple<int>; 
    
  3. swig の実行
    rm -f triple_wrap.*
    swig2.0 -ruby -c++ triple.i 
    

    [image]
  4. extconf.rb の作成

    「create_makefile('MyCPP')」と記述しているので、MyCPP.so が生成されることになる

    require 'mkmf'
    
    dir_config('triple')
    $libs += " -lstdc++ "
    if have_header('triple.hpp') 
      create_makefile('MyCPP')
    end
    
  5. ビルド
    ruby extconf.rb
    make CC=g++
    

    [image]

    nm で確認してみる

    [image]
  6. インストール
    sudo make site-install
    

    [image]
  7. 使ってみる
    irb
    
    require 'MyCPP'
    a = MyCPP::IntTriple.new
    a.set_x(1)
    a.set_y(2)
    a.set_z(3)
    a.x
    a.y
    a.z 
    

    [image]



以下、かきかけ

octave.i を次のように作成

%module Octave
%{
#include "/usr/local/include/octave-3.6.2/octave/config.h"
#include "/usr/local/include/octave-3.6.2/octave/idx-vector.h"
#include "/usr/local/include/octave-3.6.2/octave/Array.h"
#include "/usr/local/include/octave-3.6.2/octave/MArray-decl.h"
#include "/usr/local/include/octave-3.6.2/octave/MArray.h"
#include "/usr/local/include/octave-3.6.2/octave/CRowVector.h"
extern RowVector real (const ComplexRowVector& a); 
extern RowVector imag (const ComplexRowVector& a); 
#include "/usr/local/include/octave-3.6.2/octave/dRowVector.h"
#include "/usr/local/include/octave-3.6.2/octave/CColVector.h"
#include "/usr/local/include/octave-3.6.2/octave/dColVector.h"
#include "/usr/local/include/octave-3.6.2/octave/mx-op-decl.h"
#include "/usr/local/include/octave-3.6.2/octave/boolMatrix.h"
#include "/usr/local/include/octave-3.6.2/octave/CMatrix.h"
#include "/usr/local/include/octave-3.6.2/octave/dMatrix.h"
%}
%rename(__assign__) operator=;
%rename(__add__) operator+;
%rename(__sub__) operator-;
%rename(__div__) operator/;
%include "/usr/local/include/octave-3.6.2/octave/config.h"
%include "/usr/local/include/octave-3.6.2/octave/idx-vector.h"
%include "/usr/local/include/octave-3.6.2/octave/Array.h"
%include "/usr/local/include/octave-3.6.2/octave/MArray-decl.h"
%include "/usr/local/include/octave-3.6.2/octave/MArray.h"
%include "/usr/local/include/octave-3.6.2/octave/CRowVector.h"
%include "/usr/local/include/octave-3.6.2/octave/dRowVector.h"
%include "/usr/local/include/octave-3.6.2/octave/CColVector.h"
%include "/usr/local/include/octave-3.6.2/octave/dColVector.h"
%include "/usr/local/include/octave-3.6.2/octave/mx-op-decl.h"
%include "/usr/local/include/octave-3.6.2/octave/boolMatrix.h"
%include "/usr/local/include/octave-3.6.2/octave/CMatrix.h"
%include "/usr/local/include/octave-3.6.2/octave/dMatrix.h"

rm -f matrix_wrap.*
swig2.0 -ruby -c++ octave.i 

[image]
rm -f *.o
g++ -I/usr/lib/ruby/1.8/x86_64-linux -I/usr/local/include/octave-3.6.2/octave -fPIC  -c -o matrix_wrap.o matrix_wrap.cxx

extconf.rb

require 'mkmf'
dir_config('octave')
$LDFLAGS = "-L/usr/local/lib/octave/3.6.2"
$libs += " -loctinterp -loctave -lcruft -lstdc++ "
create_makefile('Octave')
ruby extconf.rb
make CC=g++

[image]
sudo make site-install

[image]
irb
require 'Octave'
a = Octave::Matrix.new(2, 3)

[image]