LoginSignup
5
2

More than 5 years have passed since last update.

C言語でマルチプラットフォーム対応のコンストラクタ処理(MSVCでの__attribute__((constructor))相当など)

Last updated at Posted at 2016-12-21

背景

 最近いじっているCのソフトに、マルチプラットフォーム対応の静的なプラグイン機構1をつけたくて、明示的に呼ばずに初期化処理を走らせる方法をいろいろ調べてみました。
 なおDLLやSOなどはエントリポイントがあるのでそちらを使ってもよいと思います。

  1. C++に妥協し、static変数のコンストラクタを使う
  2. __attribute__((constructor))を使う(gcc拡張)
  3. .CRT$X??セクションに配置する(VCのCRT機能)

Stack Overflowの以下の回答がわかりやすいです。
c - __attribute__((constructor)) equivalent in VC? - Stack Overflow

コードも抜粋しておきます。public domainなので、使いやすくてよいですね。

initializer.c
    // Initializer/finalizer sample for MSVC and GCC/Clang.
    // 2010-2016 Joe Lowe. Released into the public domain.
#include <stdio.h>
#include <stdlib.h>

#ifdef __cplusplus
    #define INITIALIZER(f) \
        static void f(void); \
        struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_; \
        static void f(void)
#elif defined(_MSC_VER)
    #pragma section(".CRT$XCU",read)
    #define INITIALIZER2_(f,p) \
        static void f(void); \
        __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
        __pragma(comment(linker,"/include:" p #f "_")) \
        static void f(void)
    #ifdef _WIN64
        #define INITIALIZER(f) INITIALIZER2_(f,"")
    #else
        #define INITIALIZER(f) INITIALIZER2_(f,"_")
    #endif
#else
    #define INITIALIZER(f) \
        static void f(void) __attribute__((constructor)); \
        static void f(void)
#endif

static void finalize(void)
{
    printf( "finalize\n");
}

INITIALIZER( initialize)
{
    printf( "initialize\n");
    atexit( finalize);
}

int main( int argc, char** argv)
{
    printf( "main\n");
    return 0;
}

参考サイト(調査時の閲覧順)


  1. 既存コードに手を入れずに、作成したCソースファイルをビルドに含めるだけで、機能一覧に登録されるような機構。ユニットテスト作成時等にも便利。 

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2