OVH Cloud OVH Cloud

Start_up code

26 réponses
Avatar
Pierre Maurette
Bonjour,
Je recherche un exemple d'implémentation qui, conformément à ce que semble
autoriser la norme, ne définirait aucune fonction main (ou WinMain, ou
autre).
J'imagine qu'une telle implémentation génèrerait un code de prologue qui
lancerait les constructeurs d'une ou plusieurs classes, dont une nommée par
exemple Application.
Si j'ai bien compris, C++Builder6 pourrait fournir cet exemple, s'il
"cachait", ou plutôt ne créait pas, et donc rendait non-éditable le fichier
NomDuProjet.cpp (macro d'instanciation de la fiche principale du projet +
WinMain()).
De toutes façons, il faut bien que, sous Windows, le lieur fournisse en fin
de compte un point d'entrée conforme au prototype WinMain() ....
Ce n'est pas pour un devoir (j'ai un peu passé l'âge), mais c'est quand même
pour un travail de rédactiion.
Bonne messe, Cordialement,
Pierre

10 réponses

1 2 3
Avatar
Thomas Abbé
bon, je ne sais pas si je te reponds a ta question.
si tu programmes en c++, il faut avoir une fonction main.
selon le C++ standard, elle doit etre de la forme
int main() ou int main(int argc, const char* argv[])
selon le C standard, aussi dautres variantes comme
void main()
sont possible, mais ce nest pas recommende.
ca depend en plus du compilateur.

thomas



"Pierre Maurette" <mmaauurreettttttee.ppiieerrrree@@ffrreeee.ffrr> schrieb
im Newsbeitrag news:3fd2dd3a$0$28692$
Bonjour,
Je recherche un exemple d'implémentation qui, conformément à ce que semble
autoriser la norme, ne définirait aucune fonction main (ou WinMain, ou
autre).
J'imagine qu'une telle implémentation génèrerait un code de prologue qui
lancerait les constructeurs d'une ou plusieurs classes, dont une nommée
par

exemple Application.
Si j'ai bien compris, C++Builder6 pourrait fournir cet exemple, s'il
"cachait", ou plutôt ne créait pas, et donc rendait non-éditable le
fichier

NomDuProjet.cpp (macro d'instanciation de la fiche principale du projet +
WinMain()).
De toutes façons, il faut bien que, sous Windows, le lieur fournisse en
fin

de compte un point d'entrée conforme au prototype WinMain() ....
Ce n'est pas pour un devoir (j'ai un peu passé l'âge), mais c'est quand
même

pour un travail de rédactiion.
Bonne messe, Cordialement,
Pierre




Avatar
Loïc Joly
Thomas Abbé wrote:

bon, je ne sais pas si je te reponds a ta question.
si tu programmes en c++, il faut avoir une fonction main.
selon le C++ standard, elle doit etre de la forme
int main() ou int main(int argc, const char* argv[])
selon le C standard, aussi dautres variantes comme
void main()
sont possible, mais ce nest pas recommende.
ca depend en plus du compilateur.


Pas tout à fait :
3.6.1 Main function
1 A program shall contain a global function called main, which is the
designated start of the program. It is implementation-defined whether a
program in a freestanding environment is required to define a main
function. [Note: in a freestanding environment, startup and termination
is implementation-defined; startup contains the execution of
constructors for objects of namespace scope with static storage
duration; termination contains the execution of destructors for objects
with static storage duration. ]

Pour ce qu'est une freestanding implementation :
1.4 Implementation compliance
A freestanding implementation is one in which execution may take place
without the benefit of an operating system, and has an implementation
defined set of libraries that includes certain language support
libraries (17.4.1.3).

En clair, c'est surtout destiné à pourvoir faire de l'embarquer en C++,
domaine où il n'y a pas d'OS, et où la notion d'une fonction main est un
peu difficile à mettre en place.

--
Loïc

Avatar
Pierre Maurette
"Loïc Joly" a écrit dans le message de news:
bqv9lv$g0j$
Thomas Abbé wrote:

bon, je ne sais pas si je te reponds a ta question.
si tu programmes en c++, il faut avoir une fonction main.
selon le C++ standard, elle doit etre de la forme
int main() ou int main(int argc, const char* argv[])
selon le C standard, aussi dautres variantes comme
void main()
sont possible, mais ce nest pas recommende.
ca depend en plus du compilateur.


Pas tout à fait :
3.6.1 Main function
1 A program shall contain a global function called main, which is the
designated start of the program. It is implementation-defined whether a
program in a freestanding environment is required to define a main
function. [Note: in a freestanding environment, startup and termination
is implementation-defined; startup contains the execution of
constructors for objects of namespace scope with static storage
duration; termination contains the execution of destructors for objects
with static storage duration. ]

Pour ce qu'est une freestanding implementation :
1.4 Implementation compliance
A freestanding implementation is one in which execution may take place
without the benefit of an operating system, and has an implementation
defined set of libraries that includes certain language support
libraries (17.4.1.3).

En clair, c'est surtout destiné à pourvoir faire de l'embarquer en C++,
domaine où il n'y a pas d'OS, et où la notion d'une fonction main est un
peu difficile à mettre en place.
Nous avons donc les mêmes sources ...

C'est l'anglais qui me perturbe. Plus précisément, le "shall contain".
Pierre


Avatar
Pierre Maurette
"Thomas Abbé" a écrit
bon, je ne sais pas si je te reponds a ta question.
si tu programmes en c++, il faut avoir une fonction main.
selon le C++ standard, elle doit etre de la forme
int main() ou int main(int argc, const char* argv[])
selon le C standard, aussi dautres variantes comme
void main()
sont possible, mais ce nest pas recommende.
ca depend en plus du compilateur.
Non, je ne pense pas que ça dépende du compilateur.

Prenez un programme qui tourne, modifiez votre :
int main(int argc, const char* argv[])
en
int pied(int argc, const char* argv[])
Le compilateur s'en tamponne (testé sous Borland et G++). Ça marche
également avec orteil(), jambe(), etc.
Le compilateur génère du code objet pour les fonctions que vous lui
proposez.
C'est le lieur qui ne veut pas de votre pied. Ou plutôt, si, il prend votre
pied, mais il lie votre code avec du code de start-up (qui varie selon la
cible spécifiée). Ce code fait le tampon entre votre code et le chargeur de
l'OS.
Si vous avez demandé une appli console, le code de start-up veut un main()
et vous avez des chances d'être portable.
Si vous construisez une appli Windows, il lui faudra un WinMain.
Une DLL, un DLLEntryPoint (et un DLLMain ).
Entrer directement sur une instance de classe principale me parait possible
(dans le futur ?). Ce que je souhaitais, c'était savoir s'il existait un
exemple.
Pierre
PS: c'est marrant, je vois deux réponses mais pas mon message. Free sans
doute.

Avatar
DINH Viêt Hoà

Si vous avez demandé une appli console, le code de start-up veut un main()
et vous avez des chances d'être portable.
Si vous construisez une appli Windows, il lui faudra un WinMain.
Une DLL, un DLLEntryPoint (et un DLLMain ).


d'ailleurs est-ce que la bibliothèque de Windows inclut un main() qui va
appeler le WinMain() ?

Je ne vois effectivement pas l'intérêt d'ajouter cette
"incompatibilité".

--
DINH V. Hoa,

etPan! - newsreader, mail user agent -- http://libetpan.sf.net/etpan

Avatar
Loïc Joly
Pierre Maurette wrote:
1 A program shall contain a global function called main, which is the
designated start of the program. It is implementation-defined whether a
program in a freestanding environment is required to define a main
function.


Nous avons donc les mêmes sources ...
C'est l'anglais qui me perturbe. Plus précisément, le "shall contain".


Et elles sont assez fiable en ce qui concerne le C++ tel que défini dans
la norme ;)

Je comprend le "shall contain" ainsi : Un programme en C++ "hosted" (la
grosse majorité) DOIT avoir une fonction main, mais un programme
"freestanding" peut en avoir une ou non, comme ça l'arrange.

--
Loïc


Avatar
Pierre Maurette
"DINH Viêt Hoà" a écrit ...
bleurps

Si vous avez demandé une appli console, le code de start-up veut un
main()


et vous avez des chances d'être portable.
Si vous construisez une appli Windows, il lui faudra un WinMain.
Une DLL, un DLLEntryPoint (et un DLLMain ).


d'ailleurs est-ce que la bibliothèque de Windows inclut un main() qui va
appeler le WinMain() ?
Pas de main() qui appelle le pied() qui appelle le WinMain() !

Il y a quand même un truc troublant (au moins sur une implémentation) : il
est possible de surcharger WinMain(). Donc, effectivement, le compilo ne lui
accorde pas le même statut que main(). Dans un pogramme standard, le
compilateur a-t-il une vision "programme" ou simplement une vision
"collection de fonction" ? Est-ce qu'une vision programme signifie autre
chose que de refuser qu'une foncton appelle main() et que main() soit
surchargée, en d'autres termes ?

Je ne vois effectivement pas l'intérêt d'ajouter cette
"incompatibilité".
L'appeler main() aurait été possible, et c'eut été catastrophique.

Le nom n'est pas important, c'est l'interface (simple) qui l'est. Le
WinMain() est souvent minuscule.
En fait, si on a un framework pour encapsuler les fonctions Windows (non
objet, pour combien de temps ?), le WinMain() peut ne faire que 3 lignes
utiles (dans un try ... catch.). On peut très bien le générer
automatiquement (RAD) et le cacher, mais ça peut être utile d'y avoir accès.

Revenons à nos moutons : en C et encore plus en C++, le main() devrait
également être tout petit.
Un programme 100% portable ne tournera que sur des machine/OS dotés d'un
mode console, dont le format d'exécutable permettra au lieur de faire en
sorte (code de prologue ou de startup) que le main() reçoive correctement
formatés les paramètres saisis par l'utilisateur. C'est le cas de DOS puis
de tous les Windows.
Mais j'ai l'impression que cette portabilité à 100%(du source de
l'application entière) est moins importante que le fait de bien séparer ce
qui est spécifique de ce qui est portable, le coeur de métier du programme,
ses classes ou fonctions. Il est clair que la portabilité de certains
utilitaires n'a pas de sens. Si le travail sur l'interface est important, il
faudra se tourner vers des solutions comme wxWindows. Ça semble séduisant,
je suis en train de le regarder sous Wondows, je verrai ensuite sous Linux.
Il est certain que sur d'autres bécannes que des micros, la portabilité
totale est plus intéressante.
Cordialement,
Pierre


Avatar
DINH Viêt Hoà

d'ailleurs est-ce que la bibliothèque de Windows inclut un main() qui va
appeler le WinMain() ?


Pas de main() qui appelle le pied() qui appelle le WinMain() !
Il y a quand même un truc troublant (au moins sur une implémentation) : il
est possible de surcharger WinMain().


Quels sont les différents prototypes de WinMain() et dans quels cas
sont-ils appelés ?

Je précise ma pensée : je ne vois pas pourquoi une fonction main() ou
WinMain() aurait besoin d'être surchargée vu qu'il n'y a qu'un seul type
d'appel possible : l'exécution du programme.

Je ne vois effectivement pas l'intérêt d'ajouter cette
"incompatibilité".


L'appeler main() aurait été possible, et c'eut été catastrophique.
Le nom n'est pas important, c'est l'interface (simple) qui l'est. Le
WinMain() est souvent minuscule.


Je ne vois pas ce que cela change par rapport à main(), peux-tu apporter
des précisions ?

Revenons à nos moutons : en C et encore plus en C++, le main() devrait
également être tout petit.


Enfin, cela dépend de l'ampleur du programme.

Un programme 100% portable ne tournera que sur des machine/OS dotés d'un
mode console


on peut tout à fait avec un main() sans affichage, donc le mode console
n'est pas nécessaire non plus (cf embarqué).

--
DINH V. Hoa,

etPan! - newsreader, mail user agent -- http://libetpan.sf.net/etpan


Avatar
Pierre Maurette
"DINH Viêt Hoà" a écrit ...
Pas de main() qui appelle le pied() qui appelle le WinMain() !
Il y a quand même un truc troublant (au moins sur une implémentation) :
il


est possible de surcharger WinMain().


Quels sont les différents prototypes de WinMain() et dans quels cas
sont-ils appelés ?

Je précise ma pensée : je ne vois pas pourquoi une fonction main() ou
WinMain() aurait besoin d'être surchargée vu qu'il n'y a qu'un seul type
d'appel possible : l'exécution du programme.
Nous sommes d'accord. Ça ne sert à rien, ça n'a pas de sens. C'est pour ça

que C++ l'interdit pour main().
Ma manip était d'ordre syntaxique.J'ai construit, mais je n'ai pas exécuté.
Donc, un compilateur va refuser toute surcharge et tout appel interne de
main(). C'est dans la norme.
Le lieur associé à mon compilateur reconnait en WinMain() le point d'entrée
du programme quand je lui demande de construire un exe Win32.
Mais pas le compilateur, qui apparemment le considère comme une fonction
ordinaire.
En d'autres termes, WinMain n'est pas un "specific" de mon compilo.
C'est juste ce dernier point que je voulais vérifier.
Je pense que je vérifie des points qui sont commentés quelque part au fin
fond des documentations ;-)
Serait-il judicieux que la norme définisse un modificateur genre
"entrypoint" pour étendre la notion de main(), qui par défaut serait
conservée ?


Je ne vois effectivement pas l'intérêt d'ajouter cette
"incompatibilité".


L'appeler main() aurait été possible, et c'eut été catastrophique.
Le nom n'est pas important, c'est l'interface (simple) qui l'est. Le
WinMain() est souvent minuscule.


Je ne vois pas ce que cela change par rapport à main(), peux-tu apporter
des précisions ?
Ben, quand les copains de Billou ont écrit les premières API Windows, le

langage support était le C. Le compilo de Billou (sans parler des autres)
n'est peut-être pas un modèle de conformité, mais il fait du C, donc gère le
main() conformément à la norme. Donc, impossible de "livrer" un proto de
main() dans winbase.h .Donc, j'ai écrit une demi connerie, il n'aurait pas
été possible tel quel de l'appeler main().
Quand à prévoir un main() intermédiare dans le seul but de respecter un
détail d'une norme, ça me parait compliqué et inutile. main() ne reçoit
qu'une collection de char*, alors que WinMain() attend trois entiers et un
char*.
On peut toujours réécrire l'histoire, mais il faut bien voir qu'en l'espèce,
le lieur était une pièce maitresse de l'édifice, en terme de gestion des
compatibilités d'exécutables (au sens large), alors autant lui demander de
traiter un WinMain() comme point d'entrée.A ce moment-là, le compilateur
travaille dans la norme, puisqu'il compile une collection de fonctions (en
C).

Revenons à nos moutons : en C et encore plus en C++, le main() devrait
également être tout petit.


Enfin, cela dépend de l'ampleur du programme.
Oui, j'ai tendance à penser qu'une petite moulinette peut avoir un gros

main(), alors que dans un plus gros projet, le main() doit être maintenu en
l'état de simple lanceur.


Un programme 100% portable ne tournera que sur des machine/OS dotés d'un
mode console


on peut tout à fait avec un main() sans affichage, donc le mode console
n'est pas nécessaire non plus (cf embarqué).
Ça, j'en était sûr en l'écrivant ;-)

Arguons donc ...
Je ne pensais pas aux PIC et automates industriels. Les implémentations
"freestanding" n'imposent aucune bib d'E/S.
Portgabilité à 100% implique implémentation complète (hosted ?).
Bibs d'E/S implique un mode console (stdout).

Cordialement,
Pierre



Avatar
DINH Viêt Hoà

En d'autres termes, WinMain n'est pas un "specific" de mon compilo.
C'est juste ce dernier point que je voulais vérifier.


main() est également considéré comme une fonction ordinaire.

Je pense que je vérifie des points qui sont commentés quelque part au fin
fond des documentations ;-)
Serait-il judicieux que la norme définisse un modificateur genre
"entrypoint" pour étendre la notion de main(), qui par défaut serait
conservée ?


ben heu ... le mot-clef éventuel "entrypoint" est implicite pour la
fonction main(), pourquoi en ajouter un ?
Enfin dans ma réponse, je suppose que la définition de la fonction
main() suffit (ce qui ne semble pas être ton cas).

Quand à prévoir un main() intermédiare dans le seul but de respecter un
détail d'une norme, ça me parait compliqué et inutile. main() ne reçoit
qu'une collection de char*, alors que WinMain() attend trois entiers et un
char*.


quels sont ces 3 entiers ?
sur Unix, on a bien des applications fenêtrées qui ont un main() on ne
peut plus classique.
Si un de ces entiers correspond à un identifiant de fenêtre ou de
processus, sous Unix, une solution qui a été employée, qui conserve la
compatibilité avec le main() historique est de définir des fonctions
donnant les informations spécifiques à un processus, par exemple
getpid() pour avoir l'identifiant de processus.

--
DINH V. Hoa,

etPan! - newsreader, mail user agent -- http://libetpan.sf.net/etpan

1 2 3