簡體   English   中英

將 C++ 方法傳遞給 Objective-C 方法

[英]Passing a C++ method to an Objective-C method

我有一個 C++ 類“ Expression ”,其中有一個我想在我的 Objective-C 類“ GraphVC ”中使用的方法。

class Expression {
    double evaluate(double);
}

還有我的 Objective-C 課程:

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

我認為傳遞帶有雙精度值並返回雙精度值的函數指針是最容易的,而不是 C++ 對象,但是我使用functional.h .h 並沒有取得太大的成功。 從 Objective-C 使用我的 C++ 方法的最佳方法是什么?

編輯:感謝您的快速回復。 請允許我詳細說明一下...我有一個用 C++ 編寫的后端,我可以在其中操作 Expression 類型的對象。 有理數、多項式、單項式等的子類。我最初的想法是使用mem_fun from ,但我無法以這種方式編譯代碼。 我也無法使用 bind1st 綁定this指針。

  • 編寫一個Objective-C 包裝器是一種可能,但我更願意使用已經存在的evaluate()函數,而且我不想打破后端和iPhone GUI 類之間的清晰分離。
  • 我不能有全局表達式或使用靜態方法(我需要繪制任意Expression實例。

我應該更明確地聲明我需要將 C++ 成員函數(不是靜態函數或現有的 C 函數)傳遞給 Objective-C 對象。 有沒有人使用 C++ 的<functional>將成員函數轉換為我可以在 Objective-C 對象中使用的指針,還是應該使用 Objective-C 包裝器?

如果要在 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;
}

我建議將 C++ 類包裝在一個 Objective-C 類中,然后還提供一個

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

除了情節:方法。

我認為這里的問題是您試圖將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++ 運行時中挖掘得足夠深,您可以做到。

如果你的 C++ 成員函數返回一個 double,你的代碼不能看起來像這樣嗎?

- (void)plot:(double)f;

...

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

或者類似的東西。 我沒有使用太多 Obj-C 和 C++ 的混合,但這就是我將如何處理它。 如果你像這樣混合它們,你可能還需要在你的 Objective-C++ 文件上有一個 .mm 擴展名。

為什么不在 NSValue 內部傳遞實例化的 c++ 類,然后直接調用 c++ 方法?

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM