Ich habe mich gefragt, ob es möglich ist, C-Konstruktoren in VC zu verwenden, so wie es möglich ist, sie in GCC zu verwenden.
Der gcc-Weg ist ziemlich gerade mit dem __attribute__
Schlüsselwort, leider scheint VC dieses Schlüsselwort nicht einmal zu kennen, da ich kein Win32-Programmierer bin, frage ich mich, ob es für solche Dinge ein äquivalentes Schlüsselwort gibt.
Nur zur Anmerkung – dies ist ein C-Programm, nicht einmal C++ oder C# (da das in diesen Sprachen ziemlich einfach war)
__attribute__((constructor)) äquivalent in VC?
Jo
Der folgende C-Code zeigt, wie eine void(void)-Funktion definiert wird, die zur Ladezeit des Programms/der Bibliothek aufgerufen wird, bevor main ausgeführt wird.
Für MSVC platziert dies einen Zeiger auf die Funktion im Benutzerinitialisierungsabschnitt (.CRT$XCU), im Grunde dasselbe, was der Compiler für die Konstruktoraufrufe für statische C++-Objekte tut. Verwendet für GCC ein Konstruktorattribut.
// 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;
}
-
Hallo Joe: toller Beitrag! Ich brauche wirklich die Tricks für die Arbeit mit VC. Es ist wichtig, eine Komponententestfunktion in C (nicht C++) automatisch zu registrieren. Übrigens: In der zweiten Zeile des Makros INITIALIZER sollte ein abschließendes \ stehen
– zhaorufei
27. September 2010 um 1:04 Uhr
-
Solche Konstruktoren werden in neuen Release-Builds von Visual Studio optimiert. Es ist ein selten bekannter und leider ungelöster Fehler. Einziger Workaround den ich bisher gefunden habe: Projekteigenschaften > C/C++ > Optimierung > Whole Program Optimization(/GL) muss deaktiviert sein.
– Benutzer3042599
8. Oktober 2015 um 16:27 Uhr
-
Ich habe das gleiche Problem wie oben beschrieben, kopieren Sie also nicht einfach den obigen Code und fügen Sie ihn ein, vorausgesetzt, er funktioniert einfach.
– CrHasher
20. November 2015 um 9:32 Uhr
-
GLib hat kürzlich von der Verwendung von
.CRT$XCU
Abschnitt zur VerwendungDllMain
deshalb: bugzilla.gnome.org/show_bug.cgi?id=752837– Amro
21. Dezember 2015 um 23:26 Uhr
-
@ user3042599. Vielen Dank für die Hinweise zu den Problemen mit MSVC 2015 Link-Time-Optimierungen. Ich habe das Codebeispiel bearbeitet und es sollte keine Probleme geben, obwohl es jetzt MSVC 2008 oder höher aufgrund der Verwendung von __pragma() erfordert.
– Jo
30. Januar 2016 um 22:22 Uhr
Sie interessieren sich wahrscheinlich für DllMain.
-
Es muss ausgeführt werden Vor Eingabe von main(), das ist für DLLs, wie hängt das zusammen? :/
– nicht so lang
11. Juli 2009 um 10:43 Uhr
-
Die einzige wirkliche Verwendung für __attribute__((constructor)) besteht darin, sie in gemeinsam genutzten Bibliotheken zu verwenden, ähnlich wie eine DllMain zu emulieren 🙂
– Nr
11. Juli 2009 um 11:00 Uhr
-
__attribute__((constructor))
ist sogar in einem einzigen Programm-Image nützlich; zum Beispiel das Einfügen globaler Hooks um Bibliotheks- und Systemaufrufe oder das Registrieren integrierter “Plugins” oder das Initialisieren von Datenstrukturen, die dynamisch verknüpfte Module in ihrem “DllMain
“-gleich.– vergänglich
11. Juli 2009 um 16:18 Uhr
Ich glaube nicht, dass es eine Möglichkeit gibt, die Verwendung von C++-Funktionen mit MSVC zu vermeiden. (Die C-Unterstützung von MSVC ist sowieso scheiße.)
Ungetestet, aber dies sollte zumindest ermöglichen, dass derselbe Code sowohl in MSVC als auch in GCC funktioniert.
#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() {
...
}
-
Soweit ich das beurteilen kann, funktioniert dies nicht in einfachem C auf MSVC 2013 oder 2015. Scheint, als würde der C-Compilermodus Konstruktoren in einer Struktur nicht unterstützen. Ich habe versucht, es auf verschiedene Weise zum Laufen zu bringen.
– guru_florida
6. September 2017 um 15:50 Uhr
Ich habe versucht, die letzte Antwort in MSVC wie
#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
aber INITIALIZER(f) kann nicht in 2 verschiedenen Dateien mit demselben Funktionsnamen vorkommen, der an INITIALIZER übergeben wird, die folgende Definition erlaubt dies
#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
für diejenigen von uns, die es nicht benutzt haben, was macht es? (Und wozu brauchst du es?)
– jalf
11. Juli 2009 um 13:24 Uhr
Jede Funktion, die als markiert ist
constructor
wird vom dynamischen Linker ausgeführt, wenn er das Objekt lädt.– Adam Goode
28. April 2010 um 3:12 Uhr
@:Jalf: Wie genau funktioniert der Attributkonstruktor?
– Casebash
22. September 2010 um 7:36 Uhr