0

現在の Xcode 4.6 プロジェクトに obj-c クラス (.mm と 2 つのヘッダー) を追加しました。1 つのヘッダー ファイルには obj-c クラスを呼び出すプロトタイプがあり、もう 1 つのヘッダー ファイルには .mm クラスが定義されています。これがどのように見えるかです。

myinterface.h

#ifndef MYINTERFACE_H
#define MYINTERFACE_H

BOOL LaunchApp(CAtlString exePath);

#endif

myLaunchClass.h

#import "myinterface.h"

@interface myLaunchClass : NSObject
-(BOOL) LaunchApp:(CAtlString)exePath;
@end

myLaunchClass.mm

@import "myLaunchClass.h"

@implementation myLaunchClass
-(BOOL) LaunchApp:(CAtlString)exePath
{
    ....
    return someCondition;
}
@end

そこから、それはうまくコンパイルされます。ビルド フェーズのターゲットに .mm ファイルを追加し、ビルド設定のヘッダー検索パスにヘッダーの場所を追加しました。

ヘッダー ファイルを .cpp ファイル ( #include "myinterface.h") に含めると、エラーは発生しません。ただし、関数 ( ::LaunchApp(exePath);) を呼び出すと、リンカー エラーが発生します。

エラー

Undefined symbols for architecture i386:
  "LaunchApp(CAtlString)", referenced from:
      myCppFile::myCppFunction() const in myCppFile.o
ld: symbol(s) not found for architecture i386

何か案は?Mac 開発者にとっては明らかな間違いだと思いますが、私は Mac プログラミングに関してはまだ少し慣れていません。どんな助けでも大歓迎です。

4

1 に答える 1

1

Objective-C++ は、この方法では相互運用できません。-(BOOL)LaunchApp:(CAtlString)exePathObjective-C クラスでインスタンス メソッドを宣言しています。そのメソッドは、Objective-C (.m、.mm) ファイルからのみ呼び出すことができます。また、メソッド シグネチャに C++ 型が含まれている場合 (ここでのように)、Objective-C++ (.mm) からのみ呼び出すことができます。ファイル。さらに、-(BOOL)LaunchApp:(CAtlString)exePathインスタンス メソッドであり、C++ の静的/クラス メソッドであるかのように呼び出しているように見えますが、これも機能しません。

Objective-C クラスをラップして、ストレートな C++ コンシューマーが利用できるようにする場合は、次のようにする必要があります。

MyLaunchClass.h :

#if __cplusplus
#import <string>
#endif

@interface MyLaunchClass : NSObject

#if __cplusplus
- (BOOL)launchApp: (std::string)str;
#endif

@end

#if __cplusplus

struct WrappedMyLaunchClass
{
    MyLaunchClass* mImpl;

    WrappedMyLaunchClass() : mImpl([[MyLaunchClass alloc] init]) { };

    ~WrappedMyLaunchClass() { mImpl = nil; }; // Assuming ARC here. for non-ARC, [mImpl release]

    bool LaunchApp(std::string str)
    {
        return !![mImpl launchApp:str];
    }
};

#endif

MyLaunchClass.mm :

#import "MyLaunchClass.h"
#import <string>

@implementation MyLaunchClass

- (BOOL)launchApp: (std::string)str
{
    NSLog(@"%s", str.c_str());
    return YES;
}

@end

SomeOtherFile.cpp :

void someOtherFunction()
{
    WrappedMyLaunchClass x;
    x.LaunchApp("foobar");
}

つまり、C++ と Objective-C++ の相互運用性を過大評価しています。Objective-C++ は、「C++ 型の変数を持つ機能と C++ コードを呼び出す機能が追加された Objective-C」と考えることができますが、「C++ 型を宣言するための代替構文」とは考えることができません。

買い手責任負担!: これは、Objective-C オブジェクトを C++ オブジェクトに有意義にラップするために必要なことを大幅に単純化しすぎています。C++ の値渡し/参照渡しのセマンティクスは、Objective-C のものとは大きく異なり、このような単純な実装は、C++ オブジェクトが値渡し (つまり、コピー コンストラクターを介して) された場合など、あらゆる種類の問題に遭遇します。 C ++オブジェクトでObjective-Cオブジェクトをラップするためのある種の汎用コードとしてではなく、試みたものが機能しない理由を示すためだけの例です。

于 2013-09-25T14:30:13.710 に答える