Intégrer du C dans Objective-C
UniX
Membre
Salut.
Voilà , j'ai un petit programme dans un fichier code.c qui contient du code de la forme :
Comment je dois faire pour l'intégrer dans mon appli en objective-c / cocoa ?
J'imagine qu'il faut importer le fichier code.c dans mon projet Xcode, mais ensuite ?
Je dois changer la valeur de toto avant l'exécution du code, et récupérer la valeur result ensuite.
Voilà , j'ai un petit programme dans un fichier code.c qui contient du code de la forme :
#include <stdio.h><br />#include <stdlib.h><br /><br />double toto=0.0;<br />int N=4;<br />double result=0.0;<br /><br /><br />void fonction1();<br />void fonction2(int param1,int param2);<br /><br /><br />int main()<br />{<br /> fonction1();<br /> fonction2();<br /> return 0;<br />}<br /><br />void fonction1()<br />{<br /> ... code fonction1<br />}<br /><br />void fonction2()<br />{<br /> ... code fonction2<br />}
Comment je dois faire pour l'intégrer dans mon appli en objective-c / cocoa ?
J'imagine qu'il faut importer le fichier code.c dans mon projet Xcode, mais ensuite ?
Je dois changer la valeur de toto avant l'exécution du code, et récupérer la valeur result ensuite.
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Ensuite, tu fais un appel C dans ton code Obj-C comme tu le ferais dans du code C.
Pour récupérer la valeur de toto, je te conseillerais de créer une nouvelle fonction similaire à main mais qui retournerais toto au lieu de retourner 0. Mais sans le reste de ton code, on ne peux pas vraiment savoir .
J'essaye donc d'intégrer ce code c dans mon objective C.
En fait fouf, tu dis "ensuite, tu fais un appel C dans ton code Obj-C comme tu le ferais dans du code C.", mais je ne sais pas comment appeler une fonction en C, surtout je ne sais pas comment dire que cette fonction est dans le fichier code.c ....
Donc ton .c contient un programme complet qui peut tourner comme un grand (enfin si les fonctions sont définies).
Mais toi, que veux tu faire ?
Si tu veux, à partir de ton code Cocoa, pouvoir appeler l'une des 2 fonctions, alors, fais sauter le main, déclares tes fonctions dans un point h à part (dans lequel tu mets les 2 includes + les prototypes de tes fonctions (comme fait juste au dessus du main) et dans ton code Cocoa, tu fais le include de ton nouveau .h et ca devrait rouler.
Sinon, si tu veux appeler le main, alors là , je sais pas trop... compiler ton programme C dans un projet bien à part, ca fait un executable Unix que tu peux alors lancer depuis ton Cocoa dans une NSTask par exemple ?
Mais là , je m'avance un peu sur un terrain inconnu... Précises ton besoin...
Mais bon étant donné que le main est un appel à fonction1 puis fonction2, je peux tout aussi bien appeler fonction1 et fonction2 depuis mon ce obj.C.
J'ai fait un .h ou je déclare toutes les fonctions. Je vais donc rajouter un include dans la classe qui va appeler les fonctions, et tenter le coup pour voir si ça marche.
Dans ton .h de ton C, tu mets juste les prototypes des fonctions, dans le . c, tu fais un include du .h précédent et tu définis les fonctions (donc le code), et dans ton Obj-C, tu fais un include du .h également pour appeler tranquillement tes fonctions.
a+
Maintenant, dans le code c, la partie haute contenait des déclarations de variables qui sont utilisées ensuite. Comment faire pour déclarer ces variables ? Je veux dire, dans le code que j'ai donné précedemment, c'est une déclaration statique, mais la valeur des variables est fonction du code exécuté avant d'appeler les fonctions en C. Il faut donc que je les initialise à la bonne valeur. Je sais pas si je suis trop clair ....
Mais bon j'essaye de deviner...
Si tu veux que tes fonctions modifient des variables (en gros, tu considères tes fonctions comme une boite noire avec des entrées et des sorties ?), rien ne t'empêche de leur passer en paramètre des variables de ton code Obj-C.
Dans ton obj-C, tu peux très bien avoir des int ou des float et tu les passe par référence à tes fonctions C. Au retour, tes variables seront modifiées.
Dans ce cas, dans ton obj C, il faut faire un appel de ce style :
fonction1(&MaVarEnEntreeSortie,MaVarEnEntreeSeulement);
Le & montre que c'est un passage par ref (tu envoie un pointeur vers ta variable en fait).
et ta fonction devra être déclarée et définie telle que :
void fonction1(int * MaVarParReference,int MaVarParCopie);
Et dans ta fonction C, faudra un peu modifier, à savoir si tu veux accèder à la valeur de ta variable passée en référence, faudra mettre *MavarParRef=tatati...
En effet tu as bien compris, les fonctions sont effectivement des "boites noires".
J'arrive presque à faire fonctionner mon code. Le dernier soucis qu'il me reste, c'est qu'un des paramètres est un tableau à plusieurs dimensions. Et là , j'ai essayé diverses façons (pointeur, direct, ...) et je n'ai pas réussi à trouver la bonne combinaison. Comment faut-il s'y prendre pour les tableaux ?
Là tu m'en demandes trop, je m'appuie sur mes connaissances C qui datent de pas mal d'annéesÂ
Mais je suis sûr que d'autres auront la réponse.
J'imagine que tu poses la question pour le paramètre de la fonction...
C'est possible mais je me rappelle plus la syntaxe...
Si c'est un tableau d'entiers, un truc comme int[][] monparam
ou peut être int ** monparam...
Mais c'est sans doute des conneries. Ca remonte à loin et se mélange avec tous les langages que j'ai pu aborder de plus ou moins près entre temps !
En fait j'ai un bouquin sur le C, j'ai essayé diverses manipulations, mais pour l'instant, le compilo hurle à chaque fois ....
En gros le contenu du ".h", quoi
En fait je crois que je cumule les problèmes. En plus de devoir passer un tableau à plusieurs dimensions en paramètre, les dimensions du tableau ne sont pas fixe. C'est pour un calcul de matrice, donc ça dépend du nombre d'équations .... Or, dans la faq, on déclare dans les paramètres de la méthode un tableau avec des dimansions fixes.
Voilà , le .h :
En fait, moi je dois envoyer la méthode pivotgauss, et ensuite resout. Les paramètres de ces méthodes sont :
- pivotgauss : N et t
- resout : N, t, et res
t est en fait la donnée d'entrée (ainsi que N qui est un paramètre), et je récupère le résultat dans res après avoir exécuté resout.
1) Les constantes sont mises dans le .h : oui pourquoi pas si c'était vraiment des constantes ! Mais là tu mets directement dans ton code (dans ton .h) la matrice 4x5 que tu souhaites résoudre ???
2) C'est quoi ce tableau double-entrée t qui est dimensionné 9x10 mais est rempli comme si c'était un 4x5 ?? Je m'étonne que le compilo accepte une telle ligne ! Et ya' des chances si jamais il l'accepte qu'il te remplisses mal ton tableau (en mettant les valeurs à la suite sans passer "à la ligne suivante dans le tableau" juste parce que tu fermes l'accolade... en tout cas j'ai jamais tenté le >:D en faisant un truc pareil moi : soit je précise le nombre de lignes et pas de colonnes (t[5][] = { {...,...,...} , ...}) soit je met la taille exacte mais quand je remplis mon tableau je l'initialise aussi avec le bon nombre de valeurs pour que ça colle !
3) Tu dis "je passe les variables machin et truc à la fonction pivotgauss et resoud" mais ces méthodes n'ont pas de paramètres !
J'imagine que je dois plutôt comprendre : il faut que je remplisse ces variables globales avant de faire appel à telle fonction car ladite fonction utilise et/ou modifie ces variables globales ?
C'est déjà pas propre du tout que de travailler avec ds variables globales, surtout que là ce n'est pas justifié, alors ça ne va pas nous aider !
4) Tu es sûr que tu ne veux pas plutôt opter pour une autre solution, si c'est pour un truc aussi classique que de résoudre un système d'équations à plusieurs inconnues par la méthode du pivot de gausse, c'est un truc assez classique. Quitte à reprendre l'idée de l'algo que tu as dans tes fonctions C, voire même si ça te chante le laisser en langage C, mais avec un truc plus propre pour passer les arguments ! (tableau malloc-qué et passé en paramètre par exemple)
Ce qui me gène déjà pour t'aider c'est surtout le point 2 : tu as un tableau 9x10 et tu le remplis (de manière statique, en plus) par des données comme si c'était un tableau 4x5...
Maintenant si tu tiens à garder ce genre de code (qui me semble pô très propre déjà rien qu'en regardant le .h et voyant que les "paramètres" sont des variables globales o_O), tu remplis ton tableau t comme tu le ferais en C, à la limite pour que ce soit plus clair, une case par une case :
[tt]t[0][0] = 1.0
t[0][1] = -2.0
// ...
t[1][0] = -3.0
// ...
N = 4
pivotgauss();
resoud();
[/tt]Et ensuite tu as dans res[0], res[1], etc tes résultats.
1 et 2) en fait c'est un bout de code en C que j'ai récupéré, et j'ai moi-même fait la découpe pour créer le .h et le .c (voir début du post). J'ai affiché la .h tel quel pour que l'on voit la structure originale du fichier .c. Bien evidemment, les variables ne sont pas initialisées de façon statique.
3) idem, j'ai laissé comme à l'origine.
4) Quelle solution ?
Bon en fait voilà mon code à l'heure actuelle :
Voilà pour le .h
Ensuite, le code qui va appeler le calcul :
Voilà
Leseul (je pense) problème qui me reste est le suivant : la tableau t à 2 dimensions est utilisé et modifié dans la méthode pivotgauss. Mais lorsque je sors de la méthode, il n'est pas modifié. J'ai essayé de le passer en pointeur (&t) dans pivotgauss, mais c'est pas mieux.
Ici, quelle que soit la valeur de a, tu n'ariveras pas à enregistrer 2 dans a comme ca. Le moyen efficace serait d'utiliser les pointeurs :
Ici, ca marchera : tu passes en argument un pointeur d'entier. *a signifie la valeur de l'entier pointé par a. Donc à la fin, la variable aura bien changé de valeur.
J'imagine que pour les tableaux, cela doit être équivalent (je sais pas, j'ai jamais essayer). Donc, le prototype de la fonction serait plutôt void resout(int N,double t[9][10],double *res[9]);
Et dans ton code, je te conseillerais de créer le tableau de résolution from scratch puis de l'assigner à rec avec un *res = monTableau;
fouf, t'as trop :fouf): car avec "double *res[9]" tu déclares un tableau de 9 pointeurs de double ...
En C, les tableaux sont passés par adresse, donc une fonction recoit en fait un pointeur, cà d que les déclarations suivantes sont équivalentes:
void maFonction( double res[9]);
void maFonction( double res[]);
void maFonction( double *res);
dans le cas d'un tableau à deux dimensions, la taille de la 1ere dimension doit être connu du compilateur, donc on peut écrire:
void pivotgauss(int N,double t[9][10]);
void pivotgauss(int N,double t[][10]);
void pivotgauss(int N,double (*t)[10]);
(*t)[10] se lit: pointeur de tableau de 10 doubles
Toujours se souvenir que l'opérateur [] est prioritaire sur *
Résultat: