IrrlichtMLNetSwig (1.2.1.531) | 2010-11-17 23:14 |
IrrlichtNetSwig (1.2.0.528) | 2010-08-14 13:23 |
近年、C#を代表とした.NETFrameworkのアプリケーションが増えてきました。 C#は.NETFrameworkの豊富なライブラリによるC++並の柔軟性とVBライクなデザイナによる開発効率性を兼ね備えた言語です。 しかし、C++で作られた既存のライブラリやフレームワークを使う機能には制限があり、 DLLの場合、クラスを公開している拡張DLLは使えず、C言語の関数を公開したレギュラーDLLしか使えません。
SWIGは拡張DLLのヘッダファイルを読込み、拡張DLLをレギュラーDLLに変換するラッパと、 そのラッパを他の言語のクラスに変換するラッパを出力するものです。 本文書ではSWIGを使って拡張DLLであるIrrlichtをC#で使えるようにした際のTipsについてまとめています。
SWIGの基本的な機能・制限は以下のとおり
サンプルコード:00_basic.zip
SWIGは専用の構文を使ってインターフェイスファイル(*.i)を作成して それをインプットとしてラッパを作成します。 最も基本的なインターフェイスファイルは以下になります。
// irrlicht.i %module "IrrlichtNet" //(1) %{ #include "irrlicht.h" //(2) %} %include "irrlicht.h" //(3)
このようなインターフェイスファイルを作ったら、以下のようにSWIGに食わせるとラッパのIrrlichtNet.cppとIrrlichtNet.hとCSファイルが出力される。
swig.exe -csharp -c++ irrlicht.i
サンプルコード:03_AddCSCode.zip
以下のように%typemapを記述します。 ただし、設定できるのはクラスに対して1つのみで、多重定義の場合は上書きされます。
多くの警告が出ると重要な警告を見逃してしまうことがあります。 そんな時には警告を出さないように制御します。 全体に適用する方法とクラス単位で適用する方法の2種類があります。
サンプルコード:04_ignoreMethod.zip
C#側でラッパを作って欲しくないメソッドやクラスを指定できます。
C++のクラス・メソッドの名前を変更できます。 またC#の予約語で使えない識別子を変更ために使ったりします。
C#のクラスにpartialをつけるとclassを複数ファイルに書くことができます。 そのため、SWIGが生成するクラスに独自のメソッドを追加することができます。
サンプルコード:05_template.zip
テンプレートはC#へ変換されません。 テンプレート付きのクラスをC#で使うにはテンプレートに型を指定して別名のクラスとして使用します。 C#にはジェネリックというテンプレートライクな機能がありますが、それには変換しません。
サンプルコード:06_wchar_t.zip
SWIG標準では、char*の引数をstringに変換しますが、ワイド文字であるwchar_t*が使われている場合があります。 その場合でも以下のよう"wchar.i"を読み込むとstringへ変換されるようになります。
SWIGでは、*.hファイルに書かれている#include文を再帰的に読み込んでくれません。
オプションで全てのincludeを読むようにもできますが、その場合標準ライブラリも読みに行ってしまうのであまり使えません。
宣言の順番もどうやら関係しているようなので、#includeのネストを解析して、順番どおりに並べる必要があります。
私の場合、次のようなツールを作ってヘッダファイルを解析し、%includeを並べました。ParseInclude.zip
サンプルコード:07_inheritance.zip
以下のようにインターフェイスファイルを書くと指定した型をC#で継承することができます。 特定の型を継承した引数を要求するC++ライブラリに有効です。
ただし、問題も多いです。
以下にC#で継承する例を示します。
- //Program.cs
- class CSharpRecever : CReceiver
- {
- override void OnReceiveMessage(int msgCode)
- {
- Console.WriteLine("Receive message:{0}", msgCode);
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- var connection = new CConnection();
- connection.SetReceiver(new CSharpRecever());
- connection.RaiseReceive(10);
- }
- }
C++へC#の配列を渡す方法です。C++で引数に配列を渡す際はポインタになりますが、 SWIGは、単なる参照渡しか、ポインタに値を格納するのか、配列渡しなのか判断できません。 そのため、引数が配列であることを指定する必要があります。 指定の方法ですが、まず"arrays_csharp.i"を%includeします。この中に配列の宣言をするための 定義が書かれています。その後、%apply文を以下のように書きます。
なお、この方法はintやdoubleなど基本型のみです。文字列配列やクラスの配列には対応していません。
以下に実際の例を示します。
上記と逆のパターンです。配列を渡してそこに値を格納するようなC++メソッドをC#から使えるようにします。 基本的には上記と同じですが、INPUTをOUTPUTにします。
以下で例を示します。
C++の引数が参照(○○&)でC#でrefを使った引数を使いたい場合、以下のように指定します。ただし、intやshortなど基本的な型のみです。enumも非対応です。
%include"typemap.i" %apply int &INOUT { int& outBegin };
以下で例を示します。
サンプルコード:02_enum_ref.zip
SWIGではintやdoubleなど基本的な型でのref、outに対応していますが、enumではできません。 以下のような書き方をするとenumでのref、outが使えます。
- //Test.h
- enum E_TYPE
- {
- TYPE_A = 0,
- TYPE_B,
- TYPE_COUNT
- };
- class CTest
- {
- E_TYPE m_type;
- public:
- void SetType(E_TYPE type)
- {
- m_type = type;
- }
- void GetType(E_TYPE& type)
- {
- type = m_type;
- }
- void GetType2(E_TYPE* type)
- {
- *type = m_type;
- }
- void Print()
- {
- switch(m_type)
- {
- case TYPE_A:
- printf("m_type=TYPE_A\r\n");
- break;
- case TYPE_B:
- printf("m_type=TYPE_B\r\n");
- break;
- default:
- printf("m_type=Unknown\r\n");
- break;
- }
- }
- };
- //Test.i
- %module "Test"
- %{
- #include "..\Test.h"
- %}
- %include"typemaps.i"
- //■enumのref対応
- %apply int &INOUT {E_TYPE& type};
- %typemap(cstype) E_TYPE& type "ref E_TYPE" //C#側の引数の型
- %typemap(csin) E_TYPE& type "ref $csinput" //C#側から中間ラッパへ渡す際の引数
- %typemap(imtype) E_TYPE& type "ref E_TYPE" //中間ラッパの型
- %typemap(ctype) E_TYPE& type "int*" //C++側の引数の型
- //■enumのout対応
- %apply int &OUTPUT {E_TYPE* type};
- %typemap(cstype) E_TYPE* type "out E_TYPE" //C#側の引数の型
- %typemap(csin) E_TYPE* type "out $csinput" //C#側から中間ラッパへ渡す際の引数
- %typemap(imtype) E_TYPE* type "out E_TYPE" //中間ラッパの型
- %typemap(ctype) E_TYPE* type "int*" //C++側の引数の型
- %include "test.h"
サンプルコード:11_dllimport.zip
"declspec(dllimport)"のようなWindows独自の構文が使われているとSWIGでエラーになることがあります。 そんな時、インターフェイスファイルでwindows.iを読み込むことで、これらの構文を無視することができます。
サンプルコード:12_nestedClass.zip
近日公開
近日公開
近日公開
近日公開
近日公開
近日公開
近日公開
近日公開
サンプルコード:09_inheritance_conflictName.zip
近日公開
サンプルコード:08_inheritance_wchar_t.zip
近日公開
近日公開
近日公開
近日公開
近日公開
近日公開
近日公開