防備録

2011年3月3日 コンピュータ
以前にこのblogでちょこっと書いたけど、仕事で組んでいるプログラムの話。
元がUNIX+C言語で開発されたプログラムをWindowsに移植するというプロジェクトで、UNIXとWindowsで同一ソースにしたいという要望がありました。
なるべく#ifdefを使わずにソースを見やすくするという方針だったので、あれこれ苦労しました。
ようやくテストフェーズになったので、メモとして残しておきます。誰得。

1 マクロで何とかする
LINUXとWindowsで同名関数に機能差がある場合とか。
#ifdef (_MSC_VER)
#define atol _atoi64  // Windows(32/64bit)ではlong型が32bitなので戻り値が桁落ちするのを防ぐ
#endif

LINUXとWindowsで変数の型に差がある場合とか。
例えばTCP/IPの部分。LINUXだとソケットはint型だがWindowsはSOCKET型。
こんなときは#typedefで型を宣言する。
#ifdef (_MSC_VER)
#typedef type_socket SOCKET
#else
#typedef type_socket int
#endif
そしてソースで型宣言している部分を書き換える。
// int socketfd;
type_socket socketfd;

これはint/long/size_t/__int64のwarning潰しにも使える。

LINUXとWindowsで同名関数の引数型に差がある場合もマクロでOK。
#ifdef (_MSC_VER)
#define bind(a, b, c) bind(a, b, (int)c)
#endif

2 代替関数を作成する。
LINUXに存在してWindowsに存在しない関数は代替関数を作成する。
int random(void) {
 UINT r = 0;
 rand_s(&r);
 return (r & INT_MAX); // Red Hat Linux64bitの戻り値0~INT_MAXに合わせる
}

pthreadやカタログ、正規表現などはこのパターン。
正規表現はここだけcppで格好悪いけどstd::tr1を使った。

3 細かなwarningに目をつぶる
Windowsだと、strcpy()などの関数を使うと「新しい関数使え」とwarningが出る。
コンパイルオプションでその警告を抑制できる。

4 ビルド時に関数のシンボル情報を要求されたら
exeとプラグインdllの関係でexe側の関数をdllがコールする場合。LINUXは問題なくビルドできるが、Windowsはシンボル情報を要求されてリンクエラーになる。
exeをビルドするときにlibファイルも生成し、そのlibファイルをdllのプロジェクトに取り込ませるという手法がある。
以下はサンプルソースというかイメージ。

/*----- test.exeのソース start -----*/
#include
#include

// prototype
__declspec(dllexport) int test_api(int mode);

int main(void)
{
 HMODULE hmod = NULL;

 hmod = LoadLibrary("plugin.dll");
 if (hmod == NULL) {
  printf("LoadLibrary() failed.\n");
 } else {
  // 処理は略
  FreeLibrary(hmod);
 }

 test_api(1);
 return 0;
}
/*----- test.exeのソース end -----*/

/*----- plugin.dllのソース start -----*/
#include

// prototype test.exeの関数
#pragma comment(lib, "test.lib")
extern int test_api(int mode);

// prototype 外部に公開する関数
__declspec(dllexport) int userexit(char *val);

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
 return TRUE;
}

int userexit(char *val)
{
 test_api(2);
}
/*----- plugin.dllのソース end -----*/

ちなみに、この手法だとtest.exeをリネームして実行したときにplugin.dllの動的ロードに失敗する。
なぜdllロードに失敗するのかは、ネットを検索してもうまい説明が見つからないんだよなぁ……


コメント

最新の日記 一覧

<<  2025年6月  >>
1234567
891011121314
15161718192021
22232425262728
293012345

お気に入り日記の更新

この日記について

日記内を検索