Jak mohu provádět pre-hlavní inicializace v C / C ++ s avr-gcc?

hlasů
8

Aby se zajistilo, že některé inicializace kód spustí dříve main(pomocí Arduino / avr-gcc) Mám kód, jako jsou následující:

class Init {
public:
    Init() { initialize(); }
};

Init init;

V ideálním případě bych chtěl, aby bylo možné jednoduše napsat:

initialize();

ale to není kompilace ...

Je tam méně upovídaný způsob, jak dosáhnout stejného efektu?

Poznámka: Kód je součástí Arduino náčrtu takže mainfunkce je automaticky generovaný a nemůže být modifikován (například volání initializepřed jakýmkoli jiným kódem).

Aktualizace: v ideálním případě inicializace by být provedena ve setupfunkci, ale v tomto případě neexistuje jiný kód v závislosti na tom, který nastane dříve main.

Položena 04/06/2009 v 12:08
zdroj uživatelem
V jiných jazycích...                            


9 odpovědí

hlasů
11

Můžete použít GCC constructoratribut , aby zajistily, že se zavolá před main():

void Init(void) __attribute__((constructor));
void Init(void) { /* code */ }  // This will always run before main()
Odpovězeno 04/06/2009 v 16:03
zdroj uživatelem

hlasů
4

Můžete provést výše nepatrně kratší, tím, že se „inicializovat“ návratový typ, a pomocí které inicializovat globální proměnnou:

int initialize();
int dummy = initialize();

Nicméně, musíte být opatrní s tím, norma nezaručuje, že výše uvedené inicializace (nebo jeden pro váš init objekt) se koná před hlavním je spuštěn (3.6.2 / 3):

Je implementace definované zda je či není dynamický inicializační (8.5, 9.4, 12.1, 12.6.1) objektu z rozsahu jmenného prostoru se provádí před prvním prohlášení o main.

Jediná věc, která je zaručeno, že inicializace proběhne před ‚figurínou‘ se někdy používá.

Více rušivé volba (pokud je to možné) by mohlo být použití „-D Hlavní = avr_main“ ve vaší makefile. Dalo by se pak přidat svůj vlastní Main takto:

// Add a declaration for the main declared by the avr compiler.
int avr_main (int argc, const char * argv[]);  // Needs to match exactly

#undef main
int main (int argc, const char * argv[])
{
  initialize ();
  return avr_main (argc, argv);
}

Alespoň tady máte záruku, že inicializace proběhne při očekávání.

Odpovězeno 04/06/2009 v 13:40
zdroj uživatelem

hlasů
3

Zde je poněkud zlo způsob, jak toho dosáhnout:

#include <stdio.h>

static int bar = 0;

int __real_main(int argc, char **argv);

int __wrap_main(int argc, char **argv)
{
    bar = 1;
    return __real_main(argc, argv);
}

int main(int argc, char **argv)
{
    printf("bar %d\n",bar);
    return 0;
}

Přidejte následující spojovacích vlajek: --wrap main

např.

gcc -Xlinker --wrap -Xlinker main a.c

Linker nahradí všechny hovory mains hovorů na __wrap_mainviz strana ld muž na--wrap

Odpovězeno 04/06/2009 v 15:46
zdroj uživatelem

hlasů
2

Můžete použít „.init *“ sekce pro přidání C kód má být spuštěn před main () (a dokonce i C runtime). Tyto úseky jsou spojeny do spustitelného souboru v závěru a vyvolat v určitém čase během inicializace programu. Můžete získat seznam zde:

http://www.nongnu.org/avr-libc/user-manual/mem_sections.html

.init1 například je slabě vázán na __init (), takže pokud definujete __init (), bude spojen a vyzval jako první věc. Nicméně, zásobník nebyl setup, takže budete muset dávat pozor na to, co děláte (používat pouze register8_t proměnné, není volání jakékoli funkce).

Odpovězeno 29/09/2009 v 11:36
zdroj uživatelem

hlasů
2

Pokud používáte prostředí Arduino, je nějaký důvod, proč nemůžete umístit do způsobu nastavení ?

Samozřejmě, že je to po Arduino specifické nastavení hardwaru, takže pokud máte takový low-level věci, které opravdu musí jít před main, pak budete potřebovat nějaký konstruktor kouzlo.

AKTUALIZACE:

Ok, pokud má být provedeno před zahájením hlavního Myslím, že jediný způsob, jak je použít konstruktor jako vy už dělat.

Vždy se můžete vytvořit preprocesoru makro ní:

#define RUN_EARLY(code) \
namespace { \
    class Init { \
        Init() { code; } \
    }; \
    Init init; \
}

Teď by to mělo fungovat:

RUN_EARLY(initialize())

Ale to není opravdu dělat věci kratší, jen pohybující se podrobného kód kolem.

Odpovězeno 04/06/2009 v 12:33
zdroj uživatelem

hlasů
2

Vaše řešení v jednoduché a čisté. Co můžete dodatečně udělat, je dát svůj kód v anonymním názvů. Nevidím žádnou potřebu, aby to lepší než to :)

Odpovězeno 04/06/2009 v 12:17
zdroj uživatelem

hlasů
0

Tam je, jak jsem hrát pre-main kódování. Existují sever init úseky provedené před hlavní, odkazuje na http://www.nongnu.org/avr-libc/user-manual/mem_sections.html initN sekcí.

Tak či onak, to funguje pouze na -O0 optimalizaci z nějakého důvodu. I přesto se snaží zjistit, jakou variantu „optimalizovány“ můj pre-hlavní assembleru pryč.

static void
__attribute__ ((naked))
__attribute__ ((section (".init8")))    /* run this right before main */
__attribute__ ((unused))    /* Kill the unused function warning */
stack_init(void) {assembly stuff}

Update, to dopadá tvrdil I tato funkce je nevyužitá, což vede k optimalizaci rutinu pryč. I byla určena zabít funkce nevyužité varování. Je stanoveno na použitý použité atribut místo.

Odpovězeno 25/05/2016 v 10:56
zdroj uživatelem

hlasů
0

Používat statické členy tříd. Oni jsou inicializovány před vstupem do hlavní. Nevýhodou je, že nemůžete ovládat pořadí inicializace členy statické třídy.

Zde je váš příklad transformována:

class Init {
private:
    // Made the constructor private, so to avoid calling it in other situation
    // than for the initialization of the static member.
    Init() { initialize(); }

private:
    static Init INIT;
};


Init Init::INIT;
Odpovězeno 04/06/2009 v 12:17
zdroj uživatelem

hlasů
0

Jistě, dát to v jednom ze svých vašich hlavičkové soubory, říkají preinit.h:

class Init { public: Init() { initialize(); } }; Init init;

a poté, v jednom ze svých kompilačních jednotek, dát:

void initialize(void) {
    // weave your magic here.
}
#include "preinit.h"

Vím, že je to kludge ale nejsem si vědom jakékoliv přenosné způsob, jak dělat pre-hlavní inicializace bez použití konstruktoru třídy provedený v rámci souboru.

Také byste měli být opatrní, z nichž více než jeden z těchto inicializační funkce, protože nevěřím, že C ++ diktuje pořadí - to by mohlo být náhodné.

Nejsem si jistý, o to „náčrtek“, o kterých jste mluvil, ale bylo by možné transformovat hlavní kompilace jednotka se scénářem před tím, než to přešlo na kompilátor, něco jako:

awk '{print;if (substr($0,0,11) == "int main (") {print "initialize();"};}'

Můžete vidět, jak by to vliv na váš program, protože:

echo '#include <stdio.h>
int main (void) {
    int x = 1;
    return 0;
}' | awk '{
    print;
    if (substr($0,0,11) == "int main (") {
        print "    initialize();"
    }
}'

generuje následující s initialize()přidanou volání:

#include <stdio.h>
int main (void) {
    initialize();
    int x = 1;
    return 0;
}

Může se stát, že nemůžete psát-proces vytvořený soubor v takovém případě byste měli tuto konečnou volbu ignorovat, ale to je to, co bych se dívat na prvním místě.

Odpovězeno 04/06/2009 v 12:17
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more