__atribute __ ((конструктор)) эквивалент в VC? - PullRequest
25 голосов
/ 11 июля 2009

Мне было интересно, возможно ли использовать конструкторы C в VC так же, как их можно использовать в GCC.
Способ gcc довольно прост с использованием ключевого слова __attribute__, к сожалению, VC, похоже, даже не знает этого ключевого слова, так как я не программист на Win32, мне интересно, есть ли какое-то эквивалентное ключевое слово для таких вещей.
Просто заметьте - это программа на C, а не на C ++ или C # (как это довольно легко сделать на этих языках)

Ответы [ 4 ]

34 голосов
/ 06 марта 2010

Ниже код C демонстрирует, как определить функцию void (void), которая будет вызываться во время загрузки программы / библиотеки перед выполнением main.

Для MSVC это помещает указатель на функцию в раздел инициализатора пользователя (.CRT $ XCU), в основном то же самое, что компилятор делает для вызовов конструктора для статических объектов C ++. Для GCC используется атрибут конструктора.

    // 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;
}
5 голосов
/ 11 июля 2009

Я не думаю, что есть способ избежать использования функций C ++ с MSVC. (Поддержка MSVC C сосет в любом случае.)

Не проверено, но это должно как минимум позволить одному и тому же коду работать и в MSVC, и в GCC.

#if defined(_MSC_VER)
struct construct { construct(void (*f)(void)) { f(); } };
#define constructor(fn) \
    void fn(void); static constructor constructor_##fn(fn)
#elif defined(__GNUC__)
#define constructor(fn)
    void fn(void) __attribute__((constructor))
#endif

static constructor(foo);
void foo() {
    ...
}
4 голосов
/ 11 июля 2009

Возможно, вы заинтересованы в DllMain .

1 голос
/ 01 ноября 2016

Я попробовал последний ответ в MSVC, как

#ifdef _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

, но INITIALIZER (f) не может появиться в 2 разных файлах с тем же именем функции, переданным в INITIALIZER, следующее определение позволит

#ifdef _MSC_VER
#define INITIALIZER(f) \
    static void f();\
    static int __f1(){f();return 0;}\
    __pragma(data_seg(".CRT$XIU"))\
    static int(*__f2) () = __f1;\
    __pragma(data_seg())\
    static void f()
#else
#define INITIALIZER(f) \
    __attribute__((constructor)) static void f()
#endif
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...