Intégrer du C dans Objective-C

UniXUniX Membre
06:51 modifié dans Actualités #1
Salut.

Voilà , j'ai un petit programme dans un fichier code.c qui contient du code de la forme :
#include &lt;stdio.h&gt;<br />#include &lt;stdlib.h&gt;<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 />&nbsp; ... code fonction1<br />}<br /><br />void fonction2()<br />{<br />&nbsp; ... 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.

Réponses

  • fouffouf Membre
    06:51 modifié #2
    Il suffit que tu importes code.c comme tu as dit (perso, je te conseillerais de faire un code.h qui déclare toutes les fonctions avant, et la ya plus qu'a importé le h. Comme ca, ca t'évite de recompiler le fichier dans lequel tu importes à  chaque fois que tu changes le code dans code.c).
    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 ;).
  • UniXUniX Membre
    06:51 modifié #3
    Je reprend un petit peu ce fil, après l'avoir laissé tomber pour faire des choses plus pressantes ....

    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 ....
  • LeChatNoirLeChatNoir Membre, Modérateur
    06:51 modifié #4
    en fait, le petit bout de code C que tu cites contient 2 fonctions et la fonction main, qui est la fonction principale.
    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...
  • UniXUniX Membre
    06:51 modifié #5
    Ben en fait, oui je veux exécuter le main.
    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.
  • LeChatNoirLeChatNoir Membre, Modérateur
    06:51 modifié #6
    voui, comme ça c'est pas mal.
    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+
  • UniXUniX Membre
    06:51 modifié #7
    Bon, pour l'appel des fonctions à  priori ça roule.

    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 ....
  • LeChatNoirLeChatNoir Membre, Modérateur
    06:51 modifié #8
    oui je comprend pas tout en fait.
    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...



  • UniXUniX Membre
    06:51 modifié #9
    Bon, merci pour ta patience LeChatNoir. J'y suis presque.

    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 ?
  • LeChatNoirLeChatNoir Membre, Modérateur
    décembre 2005 modifié #10
    Arrggg, la question qui tue...

    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 !
  • UniXUniX Membre
    06:51 modifié #11
    Oui effectivement, je voudrais passer un tableau en paramètre d'une des fonctions.

    En fait j'ai un bouquin sur le C, j'ai essayé diverses manipulations, mais pour l'instant, le compilo hurle à  chaque fois ....
  • Eddy58Eddy58 Membre
    06:51 modifié #12
    Jette un oeil sur cette faq où tu trouveras normalement réponse. :)
  • AliGatorAliGator Membre, Modérateur
    06:51 modifié #13
    Sinon si tu nous montrais les prototypes de tes fonctions C (voire une description des paramètres à  passer quoique les types dans le proto suffiront sans doute), on pourrait t'aider sur l'appel.

    En gros le contenu du ".h", quoi ;)
  • UniXUniX Membre
    06:51 modifié #14
    Ouais, parceque j'ai jeté un oeil sur la faq, et je colle pas non plus avec ce qui est présenté ...
    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 :
    #include &lt;math.h&gt;<br />#include &lt;stdio.h&gt;<br />#include &lt;string.h&gt;<br />#include &lt;stdlib.h&gt;<br /><br />double t[9][10]={{1.,-2.,5.,0.,7,},<br />{-3.,2.,0.,-7,-2.},<br />{8.,4.,-3.,8.,10.},<br />{1.,-4.,4.,-1.,-8,}};<br />double buff[10];<br />double res[9];<br />int N=4;<br /><br />void echange(int l1,int l2);<br />void ponder(int l1,double co1,int l2,double co2);<br />void pivotgauss();<br />void resout();
    


    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.
  • UniXUniX Membre
    06:51 modifié #15
    Bon, en fait, je vais me simplifier la vie, je vais mettre une taille fixe pour mon tableau.
  • AliGatorAliGator Membre, Modérateur
    06:51 modifié #16
    Oula il m'a l'air horrible ton code, rien qu'ne voyant le .h !

    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.
  • UniXUniX Membre
    06:51 modifié #17
    Bon, alors pour répondre à  tes interrogations :

    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 :
    #include &lt;math.h&gt;<br />#include &lt;stdio.h&gt;<br />#include &lt;string.h&gt;<br />#include &lt;stdlib.h&gt;<br /><br />void pivotgauss(int N,double t[9][10]);<br />void resout(int N,double t[9][10],double res[9]);
    


    Voilà  pour le .h
    Ensuite, le code qui va appeler le calcul :
    /* code qui va remplir le tableau t<br />double t[9][10]=...;<br />double res[9];<br />int N=4;*/<br />	<br />pivotgauss(N,t);<br />resout(N,t,&amp;res);
    


    Voilà 
  • UniXUniX Membre
    06:51 modifié #18
    Bon, je progresse  :P

    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.
  • fouffouf Membre
    06:51 modifié #19
    Normal. Fais un petit essai :
    <br />void fct(int a){<br />&nbsp;  a =2;<br />}<br />
    

    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 :

    <br />void fct(int *a){<br />&nbsp;  *a = 2;<br />}<br />
    


    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;
  • mpergandmpergand Membre
    06:51 modifié #20
    Salut à  tous,

    dans 1134567787:

    Donc, le prototype de la fonction serait plutôt void resout(int N,double t[9][10],double *res[9]);


    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 *

  • UniXUniX Membre
    06:51 modifié #21
    Et donc, pourquoi est ce que je ne récupère pas les valeurs de t après être passé dans pivotgauss ? Si c'est un pointeur qui est passé en paramètre, les valeurs devraient être modifiées ....
  • mpergandmpergand Membre
    06:51 modifié #22
    Je ne sais pas  :)

    <br />#include &lt;stdio.h&gt;<br /><br />double t[9][10];<br /><br />void tab(double (*t)[10]);<br /><br />int main (int argc, const char * argv&#91;]) {<br /> <br />	t[1][2]=100;<br />	tab(t);<br /><br />	printf(&quot;d[2][3] %lf&#092;n&quot;,t[2][3]);<br />	<br />&nbsp; &nbsp; return 0;<br />}<br /><br /><br /><br /><br />void tab(double (*t)[10])<br />{<br />	printf(&quot;d[1][2] %lf&#092;n&quot;,t[1][2]);<br />	t[2][3]=300;<br />}<br />
    

    Résultat:

    d[1][2] 100.000000
    d[2][3] 300.000000
  • UniXUniX Membre
    06:51 modifié #23
    Bon super ça marche ...!!!!

    <3 <3 <3
Connectez-vous ou Inscrivez-vous pour répondre.