180

Si par "pas de convention d'appel particulière" tu entends genre cdecl, de base c'est mort. (T'es obligé de connaître la convention d'appel, le reste tu peux t'en démerder tongue)
Après ça se fait très bien en assembleur [inline] mais c'est pas portable... Et ça tombe très bien car les conventions d'appel ne sont pas portables :]
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

181

Zephyr (./175) :
d'ailleurs pour confirmation, il n'existe pas de façon portable de réaliser un appel de fonction avec un nombre quelconque de paramètres de types quelconques non connus en temps de compilation ?

Tu peux abuser de la compatibilité K&R et déclarer tes fonctions comme void (*)(), ce qui fait que tu peux passer n'importe quoi. Mais ça ne marchera pas forcément partout: par exemple dans TIGCC, ça foirera évidemment si ta fonction attend ses paramètres dans des registres.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

182

./181 > En gros tu réponds pas à sa question tongue
Si c'est pour se limiter à une solution qui utilise la convention d'appel C(decl), je crois qu'on lui a déjà proposé les varargs, qui eux, sont portables tongue
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

183

Non plus, du moins pas dans le sens où il l'entend. Les varargs ont souvent une convention d'appel particulière, par exemple si tu utilises TIGCC avec -mregparm, les fonctions varargs passent quand-même tous les paramètres sur la pile. Donc tu ne peux pas utiliser un pointeur sur varargs pour appeler une fonction non-varargs.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

184

Kevin Kofler (./181) :
void (*)()

Ca veut dire quoi le (*) ? J'ai déjà vu ça dans des sources, je vois pas ce que ça signifie.

185

Heu empiler les paramètres sur la pile (par ordre inverse - puis les dépiler une fois l'appel effectué) c'est bien la convention d'appel du langage C non ? embarrassed
Si tu changes la convention d'appel dans le programme après hein...
./184 > Le (*) sert pour définir les [pointeurs de] fonctions (cf. les posts précédent d'ailleurs ^^)
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

186

C'est ce qui reste de void (*func)() après suppression du nom de variable, donc le type correspondant à cette déclaration (c'est comme ça qu'on note un type en C). Et les parenthèses sont nécessaires pour le distinguer d'une fonction qui retourne un void *.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

187

GoldenCrystal (./185) :
Heu empiler les paramètres sur la pile (par ordre inverse - puis les dépiler une fois l'appel effectué) c'est bien la convention d'appel du langage C non ? embarrassed

Non. Le standard C ne prescrit aucune convention particulière. Par exemple, sous GNU/Linux x86_64, le passage par registres est utilisé par défaut (mais seulement pour les fonctions non-varargs là aussi).
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

188

Pourquoi peut-on écrire les SCR_RECT directement dans le code :
ScrRectFill (&(SCR_RECT){{0,0,239,15}}, &Clip, A_NORMAL);

mais pas les WIN_RECT ?
DrawClipRect (&(WIN_RECT){{0,0,239,127}}, &Clip, B_DOUBLE);
? confus

189

Car ta déclaration est fausse dans le 2e, y'a une paire d'accolade de trop.
(SCR_RECT est une union avec une structire dedans, donc deux paires d'accolades imbriquées, WIN_RECT est juste une structure donc une seule paire d'accolades)
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

190

Ah, j'ma fait baisé, merci. happy

191

De quelle manière un programme kernel compilé avec --remove-unused peut-il faire que 89 octets, alors qu'il devrait en faire dans les 300 ? main() appelle a() qui appelle b() qui dessine à l'écran. Quand j'enlève --remove-unused, tout rentre dans l'ordre (enfin, presque).
main.c
#include  "unedit.h"
#include  "kernel.h"
#include  "genlib.h"
#include  "funcs.h"
#include  "vars.h"

unsigned short MapWidth = 0;
unsigned short MapHeight = 0;
const SCR_RECT Clip = {{0,0,239,127}};

void main(void)
{
  NewMap();
}

et le fichier qui contient newmap :
menu.c
#include  "unedit.h"
#include  "kernel.h"
#include  "genlib.h"
#include  "funcs.h"
#include  "vars.h"

void DrawBox(char* title)
{
  ScrRectFill (&Clip, &Clip, A_REVERSE);
  ScrRectFill (&(SCR_RECT){{0,0,239,15}}, &(SCR_RECT)Clip, A_NORMAL);
  DrawStr (3, 3, title, A_REVERSE);
  DrawClipRect (&(WIN_RECT){0,0,159,99}, &(SCR_RECT)Clip, B_DOUBLE);
  ngetchx();
}

void NewMap (void)
{
  DrawBox ("New Map");
}


En plus, le DrawStr marche mais pas les dessins de rectangle, 1/2h que je suis dessus et je comprends pas fou A priori c'est au niveau de Clip que ça déconne.
edit -> Bon les rectangle marchent (oublié extern sick), mais toujours le problème avec --remove-unused...

J'ai honte de poster ça, je sens que je vais me prendre le gros vent du débutant, mais yen a marre mad

192

C'est probablement kernel.h qui fait quelque chose de non-standard qui laisse le linker confus (genre du bidouillage pour supprimer le code de démarrage). Ce n'est pas sans raison que ce header n'est pas supporté.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

193

J'ai aussi pensé que le problème pouvait venir de kernel.h, mais sans trouver quoi (ça m'aurait étonné de moi ^^). On va attendre l'avis de Monsieur Kernel.h. En attendant, ça marche très bien sans ce switch.

194

Normalement, ta fonction _main (qui est renommée en __main par un #define dans tigcclib.h) est appellée par le code de démarrage, donc toujours utilisée. Le code de démarrage, lui (qui n'est jamais supprimé par --remove-unused), définit le vrai point d'entrée _main.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

195

Pourquoi _main d'ailleurs et pas "main" comme c'est classiquement ?
avatar
Proud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

196

Pour la compatibilité antérieure, et parce que le prototype n'est pas conforme au main du C ISO de toute façon (pas de valeur de retour, pas de gestion des arguments).
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

197

Kevin Kofler (./181) :
Tu peux abuser de la compatibilité K&R et déclarer tes fonctions comme void (*)()

Les déclarer oui, mais c'est surtout les appeler qui pose problème ensuite. Il faudrait une syntaxe permettant de pousser les paramètres un à un sur la pile, par exempl
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

198

J'avoue que ça serait utile d'avoir une api dynamique pour ça.

c'est ce qu'on fait avec printf, en fait, mais ce n'est pas changeable au runtime. Enfin, ça foutrait bien la merde si on ne libérait pas le stack frame qu'on vient de créer confus

edit: en fait ce que tu veux, c'est ce que font les JIT quand ils compilent du java ou du javascript en natif

199

Mais printf c'est des varargs et c'est "standard"... Vous lisez les trucs des fois ? T_T
(Et cf ce qu'à dit Kevin, ça marchera pas avec des fonctions "pas prévues pour", donc hors x86 ou 68k standard par exemple, y'a rien de garanti)
Après je vois pas ce que vous voulez dire par "changeable au runtime"...
La fonction que t'appelles en C, de base si tu as son pointeur, c'est que tu l'as récupérée quelque part, donc que tu connais son prototype, donc que tu peux l'appeler directement... Ou j'ai manqué un truc ? confus
Le seul cas où ça pourrait se poser c'est si tu voulais... par exemple... demander à l'utilisateur d'entrer le nom d'une fonction [que tu connais pas] puis l'appeler avec des paramètres [que tu connais pas encore]... Mais c'est complètement con car tu as quasi 100% de chances de faire planter ton programme à la moindre manipulation débile :/
Les JIT peuvent faire ça (et sont un peu obligé pour interfacer avec du natif, mais pour le coup justement je pense que c'est ni le cas de Java ni de Javascript... A moins que pour java tu aies autre chose que l'infame JNI ?) mais c'est dans un contexte bien différent...
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

200

Et on pourrait pas utiliser des types union ? triloveedit :
Zephyr (./175) :
(sachant que prévoir les 1092 prototypes possibles pour des fonctions de 1 à 6 arguments char/short/long n'est pas super élégant comme solution biggrin.gif )
ah j'avais oublié que tu voulais être *totalement* générique.

Bon en même temps le C n'est pas un langage fonctionnel, c'est pas nouveau cheeky c'est grosso modo du lisp ce que tu veux faire là ^^
avatar
« Le bonheur, c'est une carte de bibliothèque ! » — The gostak distims the doshes.
Membrane fondatrice de la confrérie des artistes flous.
L'univers est-il un dodécaèdre de Poincaré ?
(``·\ powaaaaaaaaa ! #love#

201

./200 > Ou même une macro-structure très simple:
typedef void (*double_pointeur_de_la_mort)(void *, void *);
#define ROX(n) struct je_code_comme_un_gros_porc_mais_je_m_en_fous ## n { int je_sais_pas_trop_quoi[n]; }; /* #trioui# */ \
    void apeller_la_fonction_ ## n(void (*la_fonction)(), struct je_code_comme_un_gros_porc_mais_je_m_en_fous ## n *les_parametres) { la_fonction(&les_parametres); }; /* kikoo ! lol ! */
#define RIX(n) (double_pointeur_de_la_mort)apeller_la_fonction_ ## n
#define NOMBRE_DE_ROXXOR/*_PRESENTS_DANS_LA_SALLE 0 * */10000

ROX(0)
ROX(1)
// Et ainsi de suite [...]
ROX(NOMBRE_DE_ROXXOR)

double_pointeur_de_la_mort apeller_la_fonction_en_vrai[NOMBRE_DE_ROXXOR] = {
    RIX(0),
    RIX(1),
    // Et la série continue...
    RIX(NOMBRE_DE_ROXXOR)
}

int *gros_bouffeur/* de mémoire */[1000];


void apeller_la_fonction(void (*la_fonction)(), void *les_para_metres, int c_la_taille_qui_compte)
{
    apeller_la_fonction_en_vrai[c_la_taille_qui_compte](la_fonction, les_para_metres);
}
trilove
(J'ai absolument pas testé le code, alors si jamais par le plus grand des hasards ça devait fonctionner, soyez assurés que ce n'était pas voulu.)
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

202

GoldenCrystal (./199) :
La fonction que t'appelles en C, de base si tu as son pointeur, c'est que tu l'as récupérée quelque part, donc que tu connais son prototype, donc que tu peux l'appeler directement... Ou j'ai manqué un truc ? confus

Pas nécessairement, imaginons que tu as un tableau de correspondance nom<->[pointeur de fonction + nombre et types des arguments attendus]. Depuis ton petit langage interprété perso, tu parses un appel à la fonction "plip" avec deux arguments 17 et 42. Tu la cherches dans ton tableau, tu trouves une structure qui te donne le pointeur de la fonction et une indication comme quoi la fonction prend 2 entiers. À partir de là, ça pourrait être cool de pouvoir faire "push (17); push (42); call (mon_pointeur_vers_la_fonction_plip);".

L'avantage serait par exemple de ne pas avoir besoin d'un wrapper pour rendre directement disponibles des fonctions système depuis un langage de script quelconque.
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

203

Ouais donc en gros tu veux faire un truc pas portable par nature... Donc c'est faisable, mais pas portable smile
La limitation vient du fait que le langage C ne possède pas de métadonnées comme le Java, C# & compagnie (à peu près tous les langages à JIT je pense).
Toi tu veux simuler (enfin, implémenter à ta manière) les métadonnées dans un langage qui en est dépourvu, donc tu dois aussi simuler toi-même l'appel de fonction en te basant sur ces métadonnées... Comme le font les autres langages mais pas le C ^^
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

204

Concrètement quand on fait un appel de fonction en C, en supposant que les arguments ne sont pas passés par registre (ok c'est une contrainte, mais acceptable à mon sens), il se passe quoi ? Il y a une adresse de retour poussée sur la pile, puis les arguments, puis on commence à exécuter les instructions à l'adresse indiquée par le pointeur de la fonction ? Si oui, je suppose que c'est un mécanisme assez générique, même si quelques variations peuvent exister, pour qu'on puisse envisager un squelette de fonctionnement commun non ?

(parcequ'à te lire on a vraiment l'impression que ce qui se passe lors d'un appel de fonction relève de la magie noire, et qu'il serait complètement impossible de le simuler autrement ; c'est peut-être vrai, mais ça m'étonne un peu)
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

205

Oui, ça relève de la magie noire ^^
Y'a des tas de conventions d'appel différentes, mais prenons le cas des plus courantes, que tu as certainement déjà rencontré
Sur nos chère TI 68k et sur x86, et normalement sur toutes les plates-formes en supposant qu'il y ait pas d'histoires de registres dans ta fonction, le comportement normal de la convention d'appel C (cdecl) est le suivant:
On empile les arguments, en partant du dernier et en respectant l'alignement des données (déjà un premier truc non portable ^^), puis on appelle la fonction (oui ça peut empiler je ne sais quels truc mais c'est pas ton job de savoir quoi exactement, ça dépend encore plus de la plate-forme cible).
Au retour de la fonction tu reçois la valeur de retour dans le(s) "premier(s) registre(s)" adapté(s) si ça tient dedans et sinon heu c'est nettement plus compliqué, mais c'est souvent un truc du genre tu alloues la mémoire avant l'appel (normal quoi) et tu files le pointeur à la fonction appelée en tant que premier (= empilé en dernier) paramètre. Et la fonction se fera (peut-être) une joie de te retourner ce pointeur comme valeur de retour (ou pas). J'avoue que ce point est plutôt flou tongue
Une fois que t'es content avec tout ça, tu commences par dépiler tous les trucs qui viennent polluer la pile, et tu continues gaiement ton exécution.

Si tu utilises stdcall (sous Win32) par exemple, c'est comme cdecl, sauf que c'est la fonction apellée (donc pas toi) qui nettoie la pile. Au moindre pet de travers, tu as foutu la pile, et donc toute l'éxécution du programme, en l'air... (Inutile de préciser que du coup ça ne gère pas les arguments variables)

En gros pour appeler une fonction, tu as besoin, de la convention d'appel utilisée (dépendant de l'architecture + plate-forme + éventuellement réglage du compilateur), de son prototype, du prototype des types utilisés dans le prototype (et de même jusqu'à ce que "types utilisés dans [...]" = 0)... Et tout ça dépend joyeusement de l'architecture. C'est pour ça que tu te simplifies bien la vie à utiliser un truc portable (c'est à dire où on te file une interface standard sur un truc non portable) qui fait ça pour toi, et quand tu peux pas, à définir des convention d'appel plus arrangeantes dans ton programme (par exemple, comme dit sally, utiliser des union)
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

206

En fait, ce que tu cherches, c'est ça? http://sourceware.org/libffi/
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

207

GoldenCrystal (./200) :
Le seul cas où ça pourrait se poser c'est si tu voulais... par exemple... demander à l'utilisateur d'entrer le nom d'une fonction [que tu connais pas] puis l'appeler avec des paramètres [que tu connais pas encore]...

cross, non? ^^
GoldenCrystal (./200) :
A moins que pour java tu aies autre chose que l'infame JNI ?

jni utilise stdarg.h

Kevin > ça supporte pas officiellement les [i386/x86_64]cdecl,stdcall,pascal mais ça s'approche d'un truc sympathique love

208

Le JNI, ça utilise de l'assembleur ou justement la libffi.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

209

./205 : bah ça m'a pas l'air insurmontable tout ça ? la responsabilité du nettoyage de la pile peut changer, on peut avoir à aligner les données sur une taille dépendant de l'archi, etc... mais ça reste des variations assez triviales d'un même modèle ; d'ailleurs libffi a l'air de faire exactement ce que j'attendais, comme quoi c'est pas si impossible que ça ^^ (merci Kevin pour le lien)
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

210

Nooun, je suis désolé, j'ai toujours ton bouquin de C, et je pesne qu'il serait sans doute plus utile chez toi que chez moi.
...