将C ++方法传递给Objective-C方法

时间:2009-07-27 12:21:39

标签: c++ objective-c function-pointers objective-c++

我有一个C ++类“Expression”,其中包含我想在Objective-C类“GraphVC”中使用的方法。

class Expression {
    double evaluate(double);
}

我的Objective-C课程:

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

我认为传递带有double并返回double的函数指针是最容易的,而不是C ++对象,但是使用functional.h并没有取得多大成功。使用Objective-C的C ++方法的最佳方法是什么?

编辑:感谢您的快速回复。请允许我详细说明......我有一个用C ++编写的后端,我操作Expression类型的对象。有理性,多项式,单项式等的子类。我最初的想法是使用mem_fun,但我无法通过这种方式编译代码。我也无法使用bind1st来绑定this指针。

  • 编写Objective-C包装器是可能的,但我宁愿使用已经存在的evaluate()函数,我也不想打破后端和iPhone GUI类之间的清晰分离。 / LI>
  • 我不能使用全局表达式或使用静态方法(我需要绘制任意Expression个实例。

我应该更明确地声明我需要将一个C ++成员函数(不是静态函数或现有的C函数)传递给Objective-C对象。有没有人幸运使用C ++的<functional>将成员函数转换为我可以在Objective-C对象中使用的指针,还是应该使用Objective-C包装器?

5 个答案:

答案 0 :(得分:2)

如果要在C ++中创建指向方法的指针,则需要包含类名,如下所示:

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;
}

请注意,您还需要该类的实例。在我的例子中,这是另一个参数,尽管你可以让它成为全局变量,或类Foo的单例实例。

虽然像jkp所说,你也可以通过使方法静态或将其转换为常规函数来解决问题。

编辑:我不确定我是否正确理解了您的问题。我认为你不需要使用功能。以下是我的示例在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;
}

答案 1 :(得分:2)

我建议在Objective-C类中包装C ++类,然后提供

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

除了情节:方法。

答案 2 :(得分:1)

我认为这里的问题是你试图将Expression类的成员函数传递给Objective-C类。这不起作用,因为它期望this指针作为该函数的第一个参数(因此签名与plot:方法所期望的签名不同。

如果你使C ++方法成为静态的,你就可以做到这一点,但是你不会因为使用标准的C函数而自行购买。

IE,如果Expression类看起来像这样:

class Expression {
    static double evaluate(double);
}

您应该可以这样称呼它:

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

正如我所说,这里没有太大的价值,因为你也可以使用标准的C函数(除非你可以在C ++类中做一些对你更有用的东西)。

我曾经尝试过使用objective-c方法尝试桥接boost :: bind()结果但是没有达到很远。我敢肯定,如果你在C ++运行时深入挖掘,你可以做到这一点。

答案 3 :(得分:0)

如果您的C ++成员函数返回一个double,那么您的代码不能只是这样吗?

- (void)plot:(double)f;

...

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

或类似的东西。我没有太多混合使用Obj-C和C ++,但这就是我接近它的方法。你也可能必须在Objective-C ++文件上加一个.mm扩展名,如果你这样混合它们。

答案 4 :(得分:0)

为什么不在 NSValue 内部传递实例化的 c++ 类,然后直接调用 c++ 方法?

- (NSValue*)getExpression
{
    Expression* e = new Expression();
    return [[NSValue alloc] initWithPointer:e];
}

- (void)callExpression(NSValue*)expression
{
    Expression* e = [expression pointerValue];
    e->evaluate();
}