2009-07-27 12 views
2

J'ai une classe C++ 'Expression' avec une méthode que j'aimerais utiliser dans ma classe Objective-C 'GraphVC'.Passage d'une méthode C++ à une méthode Objective-C

class Expression { 
    double evaluate(double); 
} 

Et ma classe Objective-C:

@implementation GraphVC : UIViewController { 
- (void)plot:(double(*)(double))f; 
@end 

Je pensais que ce serait plus facile de passer autour des pointeurs de fonction qui prennent un double et le retour d'un double, par opposition à des objets C++, mais je n'ont pas eu beaucoup de succès en utilisant functional.h. Quelle est la meilleure façon d'utiliser ma méthode C++ depuis Objective-C?

EDIT: Merci pour vos réponses rapides. Permettez-moi d'élaborer un peu ... J'ai un backend écrit en C++ où je manipule des objets de type Expression. Il y a des sous-classes pour rationnel, polynomial, monomial, etc. Mon idée initiale était d'utiliser mem_fun, mais je n'ai pas pu obtenir de code de cette façon. J'ai également eu du mal à utiliser bind1st pour lier le pointeur this.

  • Écrire une enveloppe Objective-C est une possibilité, mais je préfère utiliser la fonction evaluate() déjà existante, et je ne veux pas briser la séparation nette entre le back-end et les classes GUI iPhone.
  • Je ne peux pas avoir une expression globale ou utiliser une méthode statique (je dois tracer des instances Expression arbitraires.

Je devrais avoir plus explicitement dit que je dois passer une fonction membre C++ (et non statique fonction ou fonction C existante) à un objet Objective-C. Est-ce que quelqu'un a eu de la chance en utilisant <functional> de C++ pour transformer des fonctions membres en pointeurs que je peux utiliser dans un objet Objective-C, ou devrais-je utiliser un wrapper Objective-C

Répondre

2

Si vous voulez faire un pointeur vers une méthode en C++, vous devez inclure le nom de classe, comme ceci:

class Foo 
{ 
    public: 
    double bar(double d) 
    { 
     return d; 
    } 
}; 

void call_using_obj_and_method(Foo *f, double (Foo::*m)(double d)) 
{ 
    (f->*m)(3.0); 
} 

int main() 
{ 
    Foo f; 
    call_using_obj_and_method(&f, &Foo::bar); 
    return 0; 
} 

Notez que vous avez besoin d'une instance de la classe ainsi. Dans mon exemple, ceci est un autre paramètre, bien que vous puissiez le laisser être une variable globale, ou une instance singleton de la classe Foo. Bien que, comme jkp l'a dit, vous pouvez également résoudre le problème en rendant la méthode statique ou en la transformant en une fonction régulière.

EDIT: Je ne sais pas si j'ai bien compris votre question. Je ne pense pas que vous devez utiliser fonctionnel. Voici comment mon exemple regarderait en Objective-C++:

#include <Cocoa/Cocoa.h> 

class Foo 
{ 
    public: 
    double bar(double d) 
    { 
     return d; 
    } 
}; 

typedef double (Foo::*fooMethodPtr)(double d); 

@interface Baz : NSObject 
{ 
} 
- (void)callFooObj:(Foo *)f method:(fooMethodPtr)m; 
@end 

@implementation Baz 
- (void)callFooObj:(Foo *)f method:(fooMethodPtr)m 
{ 
    (f->*m)(3.0); 
} 
@end 

int main() 
{ 
    Foo f; 
    Baz *b = [[Baz alloc] init]; 
    [b callFooObj:&f method:&Foo::bar]; 
    return 0; 
} 
0

Si votre fonction membre C++ renvoie un double, votre code ne peut-il pas ressembler à ceci:

- (void)plot:(double)f; 

...

[self plot:myExpression.evaluate(aDouble)]; 

ou quelque chose de similaire. Je n'ai pas beaucoup mélangé Obj-C et C++, mais c'est comme ça que je l'aborderais. Vous devrez également avoir une extension .mm sur votre fichier Objective-C++ si vous les mélangez comme ça.

+0

Je pense qu'il veut passer une fonction à la méthode 'plot:', pas une seule valeur. – dreamlax

1

Je pense que le problème ici est que vous essayez de transmettre une fonction membre de votre classe Expression à la classe Objective-C. Cela ne fonctionnera pas car il attend un pointeur this comme premier argument à cette fonction (par conséquent, la signature n'est pas le même que celui attendu par la méthode .

Si vous faites la méthode C++ statique, vous pouvez faire ceci, mais alors vous ne vous achetez pas beaucoup en utilisant une fonction C standard.

IE, si la classe Expression ressemblait à ceci:

class Expression { 
    static double evaluate(double); 
} 

Vous devriez pouvoir l'appeler comme ceci:

[self plot:myExpression.evaluate(&Express::evalulate)]; 

Comme je le dis bien, il n'y a pas une quantité énorme de valeur dans ce cas car vous pouvez aussi bien utiliser une fonction C standard (sauf si vous pouvez faire quelque chose dans la classe C++ qui vous est plus utile).

J'ai jeté un coup d'oeil en essayant de rapprocher les résultats de boost :: bind() avec des méthodes objectives-c mais je ne suis pas allé très loin. Je suis sûr que si vous creusez assez profond dans le runtime C++ vous pourriez le faire cependant.

2

Je suggère enroulant la classe C++ dans une classe Objective-C, puis fournissant également une

- (void) plotWithObject:(id)obj 
{ 
    double result = [obj evaluate: 1.5]; 
    // ... etc ... 
} 

en plus de l'intrigue : méthode.

Questions connexes