yop, J'aimerais savoir comment faire une lib dynamique en C. Dans la doc, il ya ça : You can produce an external library file by defining the global symbol _library, i.e. by putting int _library in your program. Ca veut dire que je mets "int _library;" quelque part et c'est bon ? C'est tout ?!? "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |
Oui. (Enfin, il faut aussi définir USE_KERNEL évidemment, cf. options du projet si tu utilises l'EDI.) |
Ok, merci. "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |
Genre tu fais du C. |
Ouais "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |
On s'endort presque à utiliser genlib en C, tout est déjà fait. [box=truc] void gl_main()
{
while( 1 )
{
// Manage non-graphical part
switch( Task )
{
}
// Wait for real screen swapping
glaux_ready();
// Manage graphical part
switch( Task )
{
}
// Wait for synchro
glaux_synchro( 1 );
glaux_swap();
}
}[/box] "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |
Tiens ben pendant que j'y suis, une question. Si j'ai deux fonctions, A et B, sans "return", mais dans lesquelles elles s'appellent mutuellement, est-ce que le programme va empiler des adresses de retour sur la pile ? ie en assembleur, j'aurais fait des bra entre les fonctions, pas des bsr. Ca se gère comment en C ? tout seul j'espère ? "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |
Ça va générer le bordel sur la pile effectivement, sauf dans les cas où une optimisation tailcall est possible. Edité par Kevin Kofler le 12-11-2009 à 15:10:37.Il vaut mieux travailler avec des boucles ou des goto dans ce cas. |
Si l'optimiseur de flot de contrôle de GCC 1) sait faire cette optimisation sur les fonctions qui s'appellement mutuellement (attention à la terminaison de la récursivité Membre de la TI-Chess Team. Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP. |
(cross, réponse à martial) Edité par squalyl le 12-11-2009 à 15:25:36.non. ça va s'appeler récursivement et remplir la pile. ce que tu veux faire ça s'appelle des threads/couroutines/tâches, faut deux piles différentes et utiliser un truc de taskswitch préemptif style je-sais-plus-le-nm-du-truc-de-ximoon alternativement ça peut se faire assez simplement (sisi https://www.unsads.com/scm/svn/squalyl/asi/systeme/P3S/test/switcher-ti68k/ user guest pass guest (je sais plus si c'est complet, je sais plus si ça marche, mais le principe y est. Dommage j'avais un truc encore plus simple que ça, je le retrouve plus edit: ah le voila #include <stdio.h> #include <setjmp.h> /* | context switch presque portable avec setjmp, longjmp | pour comprendre setjmp et longjmp voir la doc : | http://www-ensimag.imag.fr/cours/Systeme/setjmp.longjmp | */ #define K 1024 #define TAILLE_PILE 4*K int mem [TAILLE_PILE]; /* memoire pour la pile du processus 1 */ int * deb_mem; int proc_actif = 0; jmp_buf buf_processus[2]; /*----------------------------------------------------------------------------*/ void ctxsw(actif, elu) { if (setjmp(buf_processus[actif]) == 0) { proc_actif = elu; longjmp(buf_processus[elu], 1); } } /*----------------------------------------------------------------------------*/ int choix_elu() { if (proc_actif == 0) return 1; else return 0; } /*----------------------------------------------------------------------------*/ void resched() { int proc_elu; proc_elu = choix_elu(); ctxsw(proc_actif, proc_elu); } /*----------------------------------------------------------------------------*/ /* | code execute par les 2 processus | */ void code_processus(char * mess) { int i; while(1) { printf ("%s", mess); resched(); /* changement de processus */ } } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int main() { deb_mem = mem; /* on pourrait faire un malloc a la place */ /* | ici c'est le processus 0 qui s'exécute avec la pile allouée au lancement du programme C */ if (setjmp(buf_processus[1]) == 0) { #ifdef LINUX /* | Initialisation de la pile pour le processus 1 (petit bricolage specifique pour linux/i386) */ buf_processus[1][0].__jmpbuf[JB_SP] = deb_mem + TAILLE_PILE; #else #ifdef SOLARIS /* | Initialisation de la pile pour le processus 1 | (petit bricolage specifique pour Solaris/Sparc) */ buf_processus[1][1] = (int) deb_mem + TAILLE_PILE - 16; #else #error "use -DLINUX or -DSOLARIS" #endif #endif printf ("Je suis le processus 0 et je pars dans la boucle\n"); code_processus("je pense\n"); } else { printf ("Je suis le processus 1 et je pars dans la boucle\n"); code_processus(" donc tu es\n"); } } Nspire wiki CONDUCTEUR Va-et-vient Des QUATRE MANCHE AVEC DES DIODES |
Pour la TI, le code spécifique à la plateforme, c'est: buf_processus[1]->A7 = (unsigned long) deb_mem + TAILLE_PILE; Mais ce hack est vraiment |
oui ce hack est mégamoche mais franchement tu connais d'autres moyens? c'est toujours la même histoire non? allocation de l'espace mémoire du nouveau processus, et changement de SP/PC plus autres registres (bien entendu sur pc c'est carrément plus compliqué avec les mmu et etc). SetJmp n'est qu'un outil userspace pratique pour les besoins de la démo. d'ailleurs pour avoir testé ça marche très bien sur 68k. Nspire wiki CONDUCTEUR Va-et-vient Des QUATRE MANCHE AVEC DES DIODES |
Kevin Kofler (./7) : Ok, je vais m'organiser autrement. squalyl (./9) : Hmm t'as vraiment pas plus simple Regarde à quel point j'en suis techniquement : char * Buffer[10] ; sprintf( Buffer , "unmap%u" , Level ); J'aurais voulu savoir si c'est valide. Il va bien y avoir un 0 à la fin de "unmap%u" ? PS -> Ca fait bien deux octets un int sur TI ? edit : sprintf( Buffer , "unmap%hu" , Level ); MapDesc = LibsBegin( Buffer , 0 ); Faut inclure quoi pour avoir les ramcalls ? J'ai inclus tigcclib.h, j'ai fait un #define USE_KERNEL, mais il veut pas de mon LibsBegin "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |
squalyl (./11) : L'autre moyen, c'est de faire une seule fonction avec des goto, voire une simple boucle si le fonctionnement est suffisamment régulier. |
Folco (./12) : Non. Un %u peut faire jusqu'à 5 caractères ("65535"), plus les 5 du "unmap" plus le \0, ça fait 11, donc ton buffer est trop petit. Il va bien y avoir un 0 à la fin de "unmap%u" ? Oui. Mais il faut le compter dans ta taille du buffer aussi! Ou dois-je écrire "unamp%u\0" ? Non. PS -> Ca fait bien deux octets un int sur TI ? Oui. |
Merci pour tout. En fait, mon argument "Level" ne peut dépasser 3 caractères, donc ça ira. C'est pour construire un nom de fichier. Par contre, j'ai un problème qui me gave bien, ça fait patrie des trucs du C qui ressemblent pour moi à une machinerie assez obscure : J'inclus "genlib.h". Dans la doc de genlib, c'est écrit ça : And you don’t need to include tigcclib since genlib.h do it for you. Et apparemment, tigcclib ne connait pas LibsBegin. Je vais donc pour inclure kernel.h de PreOS, header kernel pour le C. Mais dans le header, je trouve ça : #if defined(NOSTUB) || defined(KERNEL) || defined(DOORS) Et c'est con, parce que dedans, il y a les définitions des romcalls. Comment faire alors ? PpHd, c'est quoi les règles de l'art en la matière ? "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |
./6 Euh je ne comprends pas pourquoi squalyl te parle de tout ça… Si effectivement tes fonctions s’appellent de façon croisée et non conditionnelle (à l’extérieur d’un if) ton programme ne terminera pas (enfin au moment du stack overflow seulement Pour résoudre ça le mieux est de faire des boucles, et le moins mieux est d’utiliser goto. [edit] : un dernier truc : teste ton code toutes les 10 lignes. Évite d’écrire des pages et des pages sans même voir si ça compile ou sans même tester si la fonctionnalité ajoutée fonctionne comme prévu. |
Merci pour les tips. Pour ce qui est de la compilation, t'inquiète pas, je suis tellement skillé que je suis obligé de tester à chaque ligne. C'est vrai qu'en assembleur, je peux écrire beaucoup sans relire ou tester, mais là c'est pas la peine. "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |
Un "int" fait 2 octets sur TI-68k (sauf si tu actives une option à la con du compilo, auquel cas les fonctions de la famille *printf ne vont plus fonctionner correctement, parce qu'elles supposent qu'un int fait 2 octets Tu peux utiliser "short", "unsigned short", "int16_t" ou "uint16_t" (les deux derniers sont dans le header <stdint.h>, qui est inclus par <inttypes.h>) si tu veux une variable 16 bits (.w), et "long", "unsigned long", "int32_t" ou "uint32_t" si tu veux une variable 32 bits. Membre de la TI-Chess Team. Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP. |
Bon, j'ai résoudru le problème de la pile : main est un scheduler qui appelle la fonction qui va bien : [box=schedule] void gl_main()
{
while(1)
{
// Schedule tasks
switch( NextTask )
{
case TASK_EXIT:
return;
case TASK_INTRO:
LoadIntro();
break;
case TASK_GAME:
LoadGame();
break;
}
CurTask = NextTask ;
InfiniteLoop();
}
}[/box] Et dans InfiniteLoop(), on fait un return si CurTask a été mis à 0 par la tâche en cours. C'est bien. Enfin presque, faut que je trouve un moyen de faire passer une valeur d'une fonction à une autre maintenant... "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |
Tiens, j'avais pas vu ce warning, j'en reste Le proto de sprintf : short sprintf (char *buffer, const char *format, ...); Mon code : char * Buffer[ 10 ] ; const char * Filename = "unmap%u" ; sprintf( Buffer , Filename , Level ); Level est un int. J'ai ce ouarningue : game.c:17: warning: passing argument 1 of '(<U9e70> = &_ROM_CALL_53)' from incompatible pointer type Pourquoi ? "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |
Parceque ton buffer, tel que déclaré, est un tableau de pointeurs vers des "char". Ce que sprintf attend c'est juste un tableau de char (donc au choix "char Buffer[10]" ou "char* Buffer" selon que tu veux du statique ou du dynamique). |
Ah, parce que un tableau est un pointeur, donc "char Buffer[10 ] est un pointeur. Merci ! "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |
Disons plutôt que, après la déclaration : char buffer[10]; On a : « buffer » est un « char * » « buffer[n] » est un « char » |
Ok, merci pour ça. "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |
Folco (./15) : #include "kernel.h" #include "genlib.h" doit marcher. |
Folco (./5) : C'est fait pour! |
Merci ! Mais j'ai fait un testcase minimal qui ressemble à ./26, et j'obtiens ça : Edité par Folco le 12-11-2009 à 20:23:47./opt/gcc4ti/lib/tigcc.a: Error: Unresolved reference to `__main'. C'est vrai que les headers C, c'est compliqué avec cette manière de pouvoir dé-définir des symboles... En plus, quand je compile avec "-Wa,-l", il me dit 1. Que j'ai encore de l'espace à gagner avec le switch -l de GAS !! 2. Que les ramcalls peuvent pas être relatifs (sans blague) et qu'il les passe en absolu. "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |
Ajoute #define _main __main tout en haut avant le premier include. |
Miracle, ça marche, bien joué. Pour faire propre, ce #define doit aller où ? edit -> je veux dire, dans quel header "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |