Convertir un callback c++ en selector objective-c

tboptbop Membre
mai 2010 modifié dans Objective-C, Swift, C, C++ #1
Bonjour à  tous !

Ma question est finalement assez simple à  résumer et pourtant je peine à  trouver une réponse claire.

Voilà , j'ai un UISlider que je veux faire communiquer avec une API C++ déjà  implémentée. Je voudrais faire la translation entre l'événement valuechanged déclenché par l'UISlider qui va le transmettre à  l'événement valuechanged géré par le Slider de l'API C++.

J'ai donc trouvé cette méthode qui est hérité de UIControl :

http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIControl_Class/Reference/Reference.html#//apple_ref/occ/instm/UIControl/addTarget:action:forControlEvents:

Cette méthode me permettrait d'appeler automatiquement une methode de ma class UICustomSlider (par exemple -(void) onValueChanged)

onValueChanged déclencherait alors un callback inclu dans ma class.

Or voilà  comment je peux rajouter ce callback c++ à  ma class objective-c ?

Est-ce que cette méthode vous semble correcte ?


<br />@interface UICustomSlider : UISlider<br />{<br />void (*callbackcpp)();<br />}<br /><br />-(void) addCallback:(void*())f<br />-(void) onValueChanged<br />@end<br />


<br />@implement UICustomSlider<br />-(id) init<br />{<br />&nbsp; self = [super init];<br />&nbsp; SEL selecteur = @selector(onValueChanged);<br />&nbsp; [self addTarget:self action:selecteur forControlEvents:UIControlValueChanged];<br />}<br /><br />-(void) addCallback:(void*())f<br />{<br /> callbackcpp = f;<br />}<br /><br />-(void) onValueChanged<br />{<br />&nbsp; callbackcpp();<br />}<br />@end<br />


Merci beaucoup !

Réponses

  • CéroceCéroce Membre, Modérateur
    14:15 modifié #2
    La réponse n'est pas si simple à  cause d'une différence fondamentale entre les deux langages:

    En C++
    Les méthodes sont implémentées sous forme de pointeurs de fonctions. L'adresse de la fonction fait partie de la classe compilée.
    Appeler une méthode est équivalent à  un appel de fonction C.

    En Objective-C
    On parle de "messages" pour les appels de méthodes, parce que c'est le Runtime ObjC qui détermine dynamiquement qui va recevoir le message. En gros, chaque message possède un identifiant unique, et chaque classe une liste des identifiants auxquels elle peut répondre. Il y a une étape intermédiaire, qui apporte un peu de lenteur mais qui rend tout plus flexible.
    Le fonctionnement est expliqué en détail dans le document sur le Runtime Objective-C.

    Bref, on ne peut pas mélanger ObjC et C++ comme on veut. Les limites sont expliquées dans le document d'Apple sur ObjC (partie sur Objective-C++).
    En gros, d'après mes souvenirs, on peut appeler des méthodes C++ depuis ObjC et vice-versa, mais c'est à  peu près tout.


    Maintenant, pour répondre à  ta question, le plus simple est sans doute d'implémenter la partie Contrôleur du pattern M-V-C en ObjC++, et que seule la partie Modèle soit en C++.
    Pour ton slider, tu implémenterais l'action comme d'habitude en ObjC:
    <br />- (IBAction) sliderMoved:(UISlider *)sender<br />{<br />	float value = [sender value];<br />	monObjetCPlusPlus-&gt;setValue(value);<br />}<br />
    


    C'est du code ObjC++, donc ton source doit porter l'extension .mm .

  • tboptbop Membre
    14:15 modifié #3
    Ouais en fait du coup j'ai vu ton message après mais j'avais pris ta solution du coup sinon ça devenait finalement très vite compliqué.

    Par contre (bon je suis un peu encore débutant avec les mécanismes iphone), d'après toi je dois juste surcharger sliderMoved en fait et pas faire le mécanisme avec addTarget:action:forControlEvent ?
  • ChachaChacha Membre
    14:15 modifié #4
    Normalement, quand on installe un callback bien fait, on lui passe une variable "contexte" (souvent un void*), ce contexte étant passé en paramètre du callback lorsqu'il est appelé.
    Dans ce cas, on peut lui passer un objet objective-C comme contexte, qui permettra alors d'appeler une méthode.
    Exemple :
    <br /><br />@implementation A<br />-(void) tuut<br />{<br />&nbsp; NSLog(@&quot;tuut&quot;);<br />}<br />@end<br /><br />...<br />void monCallBackPouet(void* context)<br />{<br />&nbsp; A* a = (A*)context;<br />&nbsp; [a tuut];<br />}<br /><br />...<br />A* a = [[A alloc] init...]<br />installerCallback(&amp;monCallBackPouet, a);<br /><br />
    
  • mpergandmpergand Membre
    mai 2010 modifié #5
    Pour le fun, un essai avec les décriés pointeurs de méthodes en CPP:
    <br />-(void) methodObjC<br />{<br />// la classe CPPClass possède une méthode callback()<br />// pour la démo je crée les instances à  la volée<br />// bien sûr, en réalité, la classe ObjC contiendra une instance de CPPClass <br /><br />	CPPClass* cppClassPtr=new CPPClass();<br />	CPPClass cppClass;<br />	<br />	void (CPPClass::*callback_ptr)();&nbsp; // pointeur de méthode<br />	callback_ptr=&amp;CPPClass::callback;&nbsp; // initialisation du pointeur<br />	(cppClassPtr-&gt;*callback_ptr)();&nbsp; // appel pour un pointeur sur une instance<br />	(cppClass.*callback_ptr)();&nbsp; // appel pour une instance<br />	<br />}
    

  • CéroceCéroce Membre, Modérateur
    mai 2010 modifié #6
    dans 1274353316:

    Par contre (bon je suis un peu encore débutant avec les mécanismes iphone), d'après toi je dois juste surcharger sliderMoved en fait et pas faire le mécanisme avec addTarget:action:forControlEvent ?


    On ne surcharge rien ici. D'ailleurs, avec Cocoa, on privilégie toujours la composition à  l'héritage.

    Le mécanisme des Targets/Actions est trop long à  expliquer ici, et par ailleurs largement expliqué dans les livres et dans les docs d'Apple; je te laisse étudier ces quelques bases, ensuite la réponse te sera évidente (la méthode addTarget:action: permet de lier les actions par le code, mais on fait plutôt ça sous Interface Builder habituellement).

    C'est pour le Mac, mais c'est pareil sur iPhone.
Connectez-vous ou Inscrivez-vous pour répondre.