__attribute__((constructor)) equivalent in VC?
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)
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; }
__attribute__((constructor)) equivalent in VC?, I was wondering if it's possible to use C constructors in VC just as it is constructor(fn) void fn(void) __attribute__((constructor)) #endif static� I've looked at __attribute__((constructor)) equivalent in VC? and CRT Initialization, which were both helpful regarding the gcc-specific __attribute__((constructor)).
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() { ... }
tenmyo/initializer.c, c - __attribute__((constructor)) equivalent in VC? - Stack Overflow. // http:// stackoverflow.com/questions/1113409/attribute-constructor-equivalent-in-vc/ 2390626#� Equivalent macro for "__attribute__" in Visual studio. OSR_Community_User Member Posts: 110,217. May 2016 in NTDEV. Hi Experts, I am working on porting device driver
You are probably interested in DllMain.
Function Attributes, In GNU C, you declare certain things about functions called in your program which help The keyword __attribute__ allows you to specify special attributes when making a declaration. Similarly, the destructor attribute causes the function to be called __attribute__ ((sentinel)) is equivalent to __attribute__ (( sentinel(0))). I was wondering what the best way to deal with code containing GCC's __attribute__ extension when using MSVC. Is the following a safe way of dealing with this: #define __attribute__(x) /* blank - should simply ignore thanks to C preprocessor */ Thanks!
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
This page provides great understanding about the constructor and destructor attribute implementation and the sections within within ELF that allow them to work. After digesting the information provided here, I compiled a bit of additional information and (borrowing the section example from Michael Ambrus above) created an example to illustrate the concepts and help my learning.
__attribute__ ((sentinel)) is equivalent to __attribute__ ((sentinel(0))) The attribute is automatically set with a position of 0 for the built-in functions execl and execlp. The built-in function execle has the attribute set with a position of 1. A valid NULL in this context is defined as zero with any pointer type.
I am using Visual c++ 6.0 for the first time in my life. My new Windows machine cannot find the "attribute" mechanism. Apparently this is because __attribute__ is gcc specific. I am trying to compile some headers that I created on my Linux box using gcc. How can I force Visual C++ to use gcc's __attribute__ mechanism? Is there a special header
__attribute__ ((sentinel)) is equivalent to __attribute__ ((sentinel(0))) The attribute is automatically set with a position of 0 for the built-in functions execl and execlp . The built-in function execle has the attribute set with a position of 1.
Comments
- for those of us who haven't used it, what does it do? (And what do you need it for?)
- Any function marked as
constructor
is run by the dynamic linker as it loads the object. - @:Jalf: How exactly does attribute constructor work?
- Hi Joe: great post! I really need the tricks for working with VC. It's critical to auto-register a unit test function in C(not C++). BTW: There should be a tailing \ in the second line of macro INITIALIZER
- Such constuctors will be optimized out in new Visual Studio release builds. Its rerely known and unfortunately unsolved bug. The only workaround I found so far: Project properties > C / C++ > Optimization > Whole Program Optimization(/ GL) must be disabled.
- I'm experiencing the same problem as described above so don't just copy paste above code assuming it will just work.
- GLib recently switched from using
.CRT$XCU
section to usingDllMain
for this reason: bugzilla.gnome.org/show_bug.cgi?id=752837 - @user3042599. Thanks for the heads up on the issues with MSVC 2015 link-time optimizations. I have edited the code sample and it should not have issues, though it now requires MSVC 2008 or later due to use of __pragma() .
- As far as I can tell this does not work in plain C on MSVC 2013 or 2015. Seems like C compiler mode doesnt support constructors in a struct. I tried to make it work in various ways.
- It must be executed before entering main(), that's for dlls, how's that related ? :/
- About the only real use people have for __attribute__((constructor)) is to use them in shared libraries similar to emulate a DllMain :)
__attribute__((constructor))
is useful even in a single program image; for example, inserting global hooks around library and system calls, or registering built-in "plugins", or initializing data structures that dynamically linked modules will need in their "DllMain
"-alikes.- The linker pragma in my answer is needed, and does have the effect that initializer function names must be unique for the whole exe/dll. See the comments under my example by user3042599, and my response. I am unaware if the change of section name is an alternate solution to the linker pragma, but it will have other side effects.