kou6839の日記

c++ 競プロ(特にcsacademy) linuxについて書きます。普段は自動車屋さんでナビ開発してます。転職先を探しています!!。

C++でのmain関数ラッパー方法

gdbserverを用いてリモートアタッチする際に、ラッパーmain関数内にてsleepを入れておき、
その際にアタッチする必要がありました。(sleepを入れておかないと、break pointより先にプロセスが進んでしまいます)

そこで
・元のmain関数が定義されているmain.cppには修正を加えない
という条件のもとで、そのようなラッパーmain関数を作成してみます。

結論から言うと、2つの方法があります。
(他にも方法があるかもしれません)

1つ目の方法

「main関数 ラッパー」などで検索すると、以下のページが見つかると思います。
qiita.com
マクロとincludeを用いた方法です。
これを実際にやってみます。

以下のようなmain.cppがあるとします。

//main.cpp
#include <stdio.h>

int main(){
  printf("main\n");
  return 0;
}

これをラップするwrapper_main1.cppを作成します。

//wrapper_main1.cpp
#include <stdio.h>

int original_main();

int main(){
  printf("wrapper_main1\n");
  original_main();
}

#define main original_main
#include "main.cpp"

実行すると、

-VirtualBox:~/test$ ./a.out 
wrapper_main1
main

のように、wrapper_main1→mainの順に呼ばれます。
wrapper_main1にsleepを入れておけば、目的が達成できます。

プリプロセッサ実行後をみると、

# 3 "wrapper_main1.cpp"
int original_main();

int main(){
  printf("wrapper_main1\n");
  original_main();
}


# 1 "main.cpp" 1


int original_main(){
  printf("main\n");
  return 0;
}
# 11 "wrapper_main1.cpp" 2

マクロとincludeで上手く元のmain関数をoriginal_mainに書き換え、実行していることがわかります。

2つ目の方法

(今回は主にこちらの方法を紹介する目的で記事を書きました。)
-Wl,--wrapオプションを使うことで、ラッパー関数を呼び出すことができます。

さきほどと同様に以下のmain関数をラップします。

//main.cpp
#include <stdio.h>

int main(){
  printf("main\n");
  return 0;
}

wrapper_main2.cppを作成します。

#include <stdio.h>

extern "C"{
int __real_main();
int __wrap_main(){
  printf("wrapper_main2\n");
  __real_main();

  return 0;
}
}

(手元の環境ではexternしないと_Z**が関数名にはいってしまい、うまくリンクできませんでした)

ビルドします。

-VirtualBox:~/test$ g++ -Wl,-wrap=main -o wrap2  main.cpp wrapper_main2.cpp 

実行します。

-VirtualBox:~/test$ ./wrap2 
wrapper_main2
main

この -WL,-wrap=mainがポイントです。
-wrapオプションをリンカに渡すことで、

  • オリジナルのmain関数を呼ぶときは __real_main()
  • ラッパーしたmain関数を呼ぶときは __wrap_main()

として、呼び出すことができます。
ややこしいですが、普通にmain()と呼ぶと__wrap_main()が、
__real_main()を呼ぶと普通のmain()が呼ばれます。

__wrap_main()内にsleep処理を入れておくことで、目的を達成することができます。




以上2つの方法を紹介しました。
どちらがどう良いか、を語るほどラッパー関数を使用していないのですが、
2つ目のほうが、余計なマクロや複雑なinclude処理をしないので簡単かなと思います。