__attribute__((constructor)) equivalent in VC?

2019-01-05 01:14发布

I was wondering if it's possible to use C constructors in VC just as it is possible to use them in GCC. The gcc way is quite straight using the attribute keyword, unfortunately VC doesn't seem to even know this keyword, as I'm not a Win32 programmer I wonder if there's some sort of equivalent keyword for such things. Just to note - this is a C program, not a C++ or C# even, (as 'twas quite easy to do that in those languages)

Anyone got a clue ?

Thanks in advance.

4条回答
一纸荒年 Trace。
2楼-- · 2019-01-05 01:58

You are probably interested in DllMain.

查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-01-05 02:03

I don't think there's a way to avoid using C++ features with MSVC. (MSVC's C support sucks anyways.)

Untested, but this should at least allow the same code to work in both MSVC and 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() {
    ...
}
查看更多
可以哭但决不认输i
4楼-- · 2019-01-05 02:08

Below C code demonstrates how to define a void(void) function to be called at program/library load time, before main executes.

For MSVC, this places a pointer to the function in the user initializer section (.CRT$XCU), basically the same thing the compiler does for the constructor calls for static C++ objects. For GCC, uses a constructor attribute.

    // 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楼-- · 2019-01-05 02:09

I tried the last answer in MSVC like

#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

but INITIALIZER(f) can't appear in 2 different files with the same function name passed to INITIALIZER, the following definition will allow that

#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
查看更多
登录 后发表回答