2011-02-02 11 views
5

mainの機能の前にいくつかのことをしたいと思います。私は複数のソースファイルを持っています。各ファイルには、mainより前に行う必要のある作業があります。これは、C++には問題なかったが、C++ではC.Cでメインの前にいくつかの関数を呼び出す

との問題、これは、2つの方法で行うことができます。グローバルクラス/構造体のコンストラクタを活用

  1. 。例えば、グローバル変数

に関数を呼び出す

  • static const int __register_dummy_ = __AddRegisterMetaInfo(...);

    しかし、Cのいずれかの方法では不可能です。明らかに、コンストラクタはありません。したがって、最初の選択肢は本質的に不可能です。

    私は2番目のオプションは可能だと思っていましたが、Cでコンパイルされていないと考えました(Visual C++でのみテストしましたが、C2099です)。 Cでは、自動ではない変数への定数のみが許可されます。

    mainの前にいくつかの関数を呼び出す方法はありますか?


    EDIT:多くの人々はちょうど私が本当にやりたいことを誤解だと思われます。この質問を簡単な方法で書いて申し訳ありません。

    私がしなければならなかったのは、MFC's approachのように、ある種のC++ランタイムクラス情報機能を実装することでした。このアプローチでは、私はすべてのソースコードからいくつかの情報を得る必要があります。たとえば、各ソースファイルにクラスの定義があり、すべての情報(クラス名や親クラスなど)を確認したいとします。最も簡単な方法は、各ファイルに静的コンストラクタを配置し、各コンストラクタがグローバルデータ構造にアクセスしてその情報を登録する方法です。しかし、私はC言語でも同様のことを実装する方法を探したかったので、単にmainpre_main_jobを呼び出すことは私には答えられません。

    この静的コンストラクタの悪用は、LLVMコンパイラスイートでも確認できます。各最適化/分析機能は、パスとして実装されます。これらのすべてのパスは、静的コンストラクタを介して登録されます。

  • +10

    「I_will_explode_if_you_call_me_from_main」と呼ばれる機能はありますか? –

    +1

    好奇心のために、なぜこれをやりたいのですか? –

    +4

    C++コンパイラをより優れたCコンパイラとして使用することが、回避策の1つです(またはソリューションに応じて)。静的初期化子のような機能をチェリーピックすることができます。 –

    答えて

    11

    多くのコンパイラ固有のソリューションについては、OpenSSLディストリビューションのfips_premain.cファイル(たとえば、hereのような場所でオンラインで見ることができます)をご覧ください。 ;それは、しかし

    # ifdef _WINDLL 
        __declspec(dllexport) /* this is essentially cosmetics... */ 
    # endif 
        void FINGERPRINT_premain(void); 
        static int premain_wrapper(void) { FINGERPRINT_premain(); return 0; } 
    # ifdef _WIN64 
    # pragma section(".CRT$XCU",read) 
        __declspec(allocate(".CRT$XCU")) 
    # else 
    # pragma data_seg(".CRT$XCU") 
    # endif 
        static int (*p)(void) = premain_wrapper; 
        /* This results in pointer to premain to appear in .CRT segment, 
        * which is traversed by Visual C run-time initialization code. 
        * This applies to both Win32 and [all flavors of] Win64. */ 
    # pragma data_seg() 
    
    +0

    それは完全にクールです。 fips_premain.cはrosettaの石のようなものです。ありがとう! –

    5

    これを達成するために、コンパイラ固有の拡張機能を使用することができます。 GCCあなたがmain前とmain(またはexit)後に実行されるコードを引き起こすことがconstructor function attribute(とマッチングdestructor属性)を使用することができます

    4

    あなたがあるため、その後(...あなたはCとC++で混合されていないと仮定すると、

    Crt0は、伝統的にmain()の前に呼び出されています。これは、あなたのC++クラスの静的コンストラクタです。あなたはそれを無効にすることができますが、それはかなり深いです。

    埋め込みプラットフォームによっては、_pre_main()および_post_main()種類のprocsがあります。しかし、それは私が考えている非標準です。

    本当に、あなたのメインエントリポイントは、よく、main()です!あなたがメイクファイルの制御になら

    、あなたは

    gcc app.c -Dmain=not_really_main 
    

    ようなもので、何か他のものであることをメインに強制そしてnot_really_main()を呼び出すためにあなたの本当のmain()にリンクすることができます。


    編集:もう一つのアプローチ:gccのリンカが実行される最初のものであるENTRYという変数、通常にcrt0を持っています。繰り返しますが、これはかなり重量があり、プラットフォームをかなり深く理解することができますが、それは別の場所で「メインを破壊する」ことができます。

    3

    (私が知っている、これは元の質問に直接答えではありません。

    MSVCの特定の部分のようなものを(FINGERPRINT_premainmain前に実行される関数である)に見えますそれも、ポータブルおよび行動で予測可能だ、1 - 、mainの内容の前にコードを実行する方法を探しています誰か)

    のための答えは、私は良いアイデアを聞きました。 main関数の最初に "mainの前に"したいものを行います(またはmainの冒頭にしたい機能を呼び出します)。

    コードを制御すると、あなたが提案(または紹介)したような壊れやすい、しばしば維持不能なハックは必要ありません。

    関連する問題