__attribute __ ((конструктор)) эквивалентен в VC?
Мне было интересно, можно ли использовать конструкторы C в VC так же, как их можно использовать в GCC.
Gcc-путь довольно прямой, используя ключевое слово атрибут, к сожалению, VC, похоже, даже не знает этого ключевого слова, так как я не программист Win32. Интересно, есть ли какое-то эквивалентное ключевое слово для таких вещей,
Просто отметим - это C-программа, а не С++ или С# четная (так как это довольно легко сделать на этих языках)
Кто-нибудь понял?
Спасибо заранее.
Ответы
Ответ 1
Ниже код C демонстрирует, как определить функцию void (void), которая будет вызываться в момент загрузки программы/библиотеки, прежде чем будет выполняться main.
Для MSVC это помещает указатель на функцию в разделе инициализатора пользователя (.CRT $XCU), в основном то же самое, что делает компилятор для вызова конструктора для статических объектов С++. Для 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;
}
Ответ 2
Я не думаю, что есть способ избежать использования функций С++ с помощью 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() {
...
}
Ответ 3
Возможно, вас интересует DllMain.
Ответ 4
Я пробовал последний ответ в 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) не может отображаться в двух разных файлах с тем же именем функции, которое передается в 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