2011-02-02 4 views
5

Me gustaría hacer algunas cosas antes de la función main. Tengo varios archivos fuente. En cada archivo, hay algo de trabajo que debe hacerse antes de main. No fue un problema en C++, pero problemático con C.Llamar algunas funciones antes de principal en C

En C++, esto se puede hacer de dos maneras:

  1. La explotación de un constructor de una clase/estructura global.
  2. Llamar a una función de una variable global

Por ejemplo, static const int __register_dummy_ = __AddRegisterMetaInfo(...);

Sin embargo, en C, ya sea maneras es imposible. Obviamente, no hay constructor. Entonces, la primera opción es intrínsecamente imposible.

Pensé que la segunda opción sería posible, pero no compilada en C (Probé solo con Visual C++. Da C2099). C solo permite una constante a una variable no automática.

¿Hay alguna manera de llamar a algunas funciones antes de main?


EDITAR: Parece que mucha gente acaba de conseguir mal lo que realmente quería hacer. Perdón por escribir esta pregunta de una manera simplificada.

Lo que necesitaba hacer era implementar una especie de característica de información de clase de tiempo de ejecución de C++, al igual que MFC's approach. En este enfoque, necesito obtener información de todos los códigos fuente. Por ejemplo, supongamos que cada archivo fuente tiene una definición de clase y me gustaría ver toda la información (por ejemplo, los nombres de clase y la clase principal). La forma más fácil es colocar un constructor estático en cada archivo, y cada constructor accede a una estructura de datos global y registra su información. Pero también quería encontrar una forma de implementar algo similar en C. Así que, simplemente llamar a pre_main_job en main no puede ser una respuesta para mí.

Tenga en cuenta que este abuso de constructor estático también se puede encontrar en el conjunto de compiladores LLVM. Cada función de optimización/análisis se implementa como un pase. Todos estos pases se registran a través de un constructor estático.

+10

¿Alguna de esas funciones se llama 'I_will_explode_if_you_call_me_from_main'? –

+1

Por curiosidad, ¿por qué querrías hacer esto? –

+4

Una solución posible (o solución, según su perspectiva) es usar su compilador C++ como un mejor compilador de C; luego puede seleccionar características como inicializadores estáticos. –

Respuesta

11

Para un número de soluciones específicas del compilador puede echar un vistazo al archivo fips_premain.c de la distribución OpenSSL (puede verlo en línea en varios lugares, here por ejemplo).

El MSVC parte específica se ve algo como (FINGERPRINT_premain siendo la función a ejecutar antes de main):

# ifdef _WINDLL 
    __declspec(dllexport) /* this is essentially cosmetics... */ 
# endif 
    void FINGERPRINT_premain(void); 
    static int premain_wrapper(void) { FINGERPRINT_premain(); return 0; } 
# ifdef _WIN64 
# pragma section(".CRT$XCU",read) 
    __declspec(allocate(".CRT$XCU")) 
# else 
# pragma data_seg(".CRT$XCU") 
# endif 
    static int (*p)(void) = premain_wrapper; 
    /* This results in pointer to premain to appear in .CRT segment, 
    * which is traversed by Visual C run-time initialization code. 
    * This applies to both Win32 and [all flavors of] Win64. */ 
# pragma data_seg() 
+0

Eso es totalmente genial. Ese fips_premain.c es como una piedra rosetta. ¡Gracias! –

5

Es posible que pueda utilizar extensiones específicas del compilador para lograr esto, p. Ej. gcc le permite utilizar el constructor function attribute (y el correspondiente destructor atributo) para provocar la ejecución de código antes y después de mainmain (o exit)

4

Suponiendo que no están mezclando en C++ con su C ... (porque entonces podría hacer los constructores estáticos en su clase C++, que es tal vez lo que está preguntando!)

Crt0 es la configuración de tiempo de ejecución específica de la plataforma llamada tradicionalmente antes de main(). Podrías anular eso, pero eso es bastante profundo.

Algunas plataformas integradas proporcionan un tipo de procs _pre_main() y _post_main(). Pero eso es no estándar, creo.

Realmente, su punto de entrada principal es, bueno, main()!

Si usted tiene el control del Makefile, se podía fuerza principal que haber algo más, con algo como

gcc app.c -Dmain=not_really_main 

Y luego enlace en su verdadera main() llamar not_really_main().


edición: un enfoque más: El enlazador gcc tiene una llamada entrada de la variable que es el primero que se ejecuta, por lo general crt0. Nuevamente, este es un peso bastante pesado, y habrás entendido la plataforma bastante bien para llevarlo a cabo, pero es otro lugar donde puedes "subvertir el main".

3

(lo sé, esto no es una respuesta directa a la pregunta original, es, sin embargo , una respuesta para alguien que está buscando una manera de ejecutar código antes de que los contenidos de main)

que he oído de una mejor idea - uno, que es incluso portátil y predecible en el comportamiento. Haga las cosas que desea hacer "antes de main" al comienzo de la función main (o llame a una función que haga lo que desee al comienzo de main).

Si controlas el código, no hay (¡realmente!) Sin necesidad de hacks frágiles y, a menudo, inmanejables como los que has propuesto (o presentado).

Cuestiones relacionadas