C言語からJavaへの移植方法まとめ

XPCEというC言語で組まれたPCエンジンエミュレータを、iアプリJavaへ移植しています。
やっているうちに、移植手順のちょっとしたコツに気がつきました。


そんなわけで、C言語のソースから、Javaへ移植する場合の作業について、まとめておきます。

常に動作テストできるようにする

Cのソースを、いきなりJavaに拡張子変更して、中身を書き換えていくという方法をとると、
すべてをJavaコードに修正するまで、動作確認することができなくなってしまいます。

Javaに拡張子変更するのは、できるだけ後にします。
Cのソースのまま、ビルドして動かせる状態を保ったままで、Javaに無い機能を置換していきます。

Javaに無い機能を置き換える

Javaに無い機能というと、

  • ポインタ演算子
  • 共用体
  • unsigned型
  • マクロ

などです。
これらを、使わない形のCソースに修正していくわけです。

ポインタ演算の置き換え

ポインタは配列+インデックスに置き換えます。

「->」を「.」に置き換え

間接メンバ参照演算子「->」を、直接メンバ参照演算子「.」に置き換えます。
Javaには「->」が存在しないためです。
これは簡単に置き換える方法があり、構造体を参照渡しにすればOKです。

void func(HOGE *hoge)
{
   hoge->aaa = 10;
   hoge->bbb = 10;
}

だったら、

void func(HOGE& hoge)
{
   hoge.aaa = 10;
   hoge.bbb = 10;
}

このように書き換えます。

共用体(union)の置き換え

共用体をクラスに置き換えて、メンバへの参照を、ゲッター、セッターを介して行うようにすることで
共用体を使用しないようにできます。

unsigned型の置き換え

Javaで符号なしの型は、char(16bit符号無)だけです。

unsigned char等は、intに置き換えます。
unsigned charの場合、255に1を加えると0に戻りますが、これはAND演算のマスクで代用します。
演算に& 0xFFをつければOKです。

マクロ

マクロはメソッドに置き換えます。
しかし多いとそれなりに面倒です。
マクロがあまりにも多用されているソースの場合、Cコンパイラプリプロセッサを一度通して
マクロを展開してしまう手もあります。
Visual C++の場合、
cl.exe /EP in.c > out.c
で、マクロを展開したソースを得ることができます。

if文は比較演算子を必ず付ける

Cの場合、ifの条件式が数値型でもOKなので、以下のような書き方をよくします。

int var = getVer();
if (var) {
    varが非ゼロの場合の処理
}

これを比較演算子を使うように書き換えます。

int var = getVer();
if (var != 0) {
    varが非ゼロの場合の処理
}

Javaでは、ifの条件式はboolean型しか使えないためです。

とにかく、ちょっとづつやっていくのがポイント

ある程度の規模と複雑さがあるソースの場合、移植時にバグを入れてしまうと後で見つけるのは困難です。

すこし直してはビルド&動作確認し、ちょっとづつやっていくのが良いです。


状況

昨日はR-TYPEがバグってしまいましたが、条件付きブレークポイントでバグの原因を突き止めることができました。
けっこういい感じに作業が進んでいます。