2

Cocoa アプリケーションで小さな C++ ライブラリを使用しています (atm は、その方法を学ぶための非常に単純な例です)。

したがって、次のような名前空間に小さな C++ クラスがあります。

namespace testlib {
class Test {
public:
    Test(unsigned a);
    Test operator+(const Test& other) const;
    Test operator+(unsigned other) const;
    Test& operator+=(unsigned other);
    Test& operator+=(const Test& other);
    unsigned getValue() const;
private:
    unsigned theValue;
};
}

次に、次のコードを含む .h ファイルがあります。

#import <Foundation/Foundation.h>
#import "testlib.h"

@interface test : NSObject {
     testlib::Test* testClass;
}

- (id)init;
- (id)add: (unsigned)value;
- (unsigned)value;
- (void)dealloc;

@property void* testClass;

@end

最後に実装 (test.mm というファイル内):

#import "test.h"

@implementation test

@synthesize testClass;

- (id)init {
 testClass = new testlib::Test(0);
 return self;
}

- (void)dealloc {
 delete testClass;
 [super dealloc];
}

- (id)add: (unsigned)value {
 *testClass += value;
 return self;
}

- (unsigned)value {
     return testClass->getValue();
}

これをコンパイルしようとすると、次のエラーが発生します。

CompileC build/testipod.build/Debug-iphonesimulator/testipod.build/Objects-normal/i386/WindowController.o WindowController.m normal i386 objective-c com.apple.compilers.gcc.4_2
 cd /Users/sausalito/eth/testipod
 setenv LANG en_US.US-ASCII
 setenv PATH "/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2 -x objective-c -arch i386 -fmessage-length=0 -pipe -std=c99 -Wno-trigraphs -fpascal-strings -fasm-blocks -O0 -Wreturn-type -Wunused-variable -D__IPHONE_OS_VERSION_MIN_REQUIRED=30000 -isysroot /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.1.3.sdk -fvisibility=hidden -mmacosx-version-min=10.5 -gdwarf-2 -iquote /Users/sausalito/eth/testipod/build/testipod.build/Debug-iphonesimulator/testipod.build/testipod-generated-files.hmap -I/Users/sausalito/eth/testipod/build/testipod.build/Debug-iphonesimulator/testipod.build/testipod-own-target-headers.hmap -I/Users/sausalito/eth/testipod/build/testipod.build/Debug-iphonesimulator/testipod.build/testipod-all-target-headers.hmap -iquote /Users/sausalito/eth/testipod/build/testipod.build/Debug-iphonesimulator/testipod.build/testipod-project-headers.hmap -F/Users/sausalito/eth/testipod/build/Debug-iphonesimulator -F/Users/sausalito/eth/testipod/../testlib/build -I/Users/sausalito/eth/testipod/build/Debug-iphonesimulator/include -I/Users/sausalito/eth/testipod/build/testipod.build/Debug-iphonesimulator/testipod.build/DerivedSources/i386 -I/Users/sausalito/eth/testipod/build/testipod.build/Debug-iphonesimulator/testipod.build/DerivedSources -include /var/folders/4f/4fSYMOmtHHSRoBf+XVFQ+k+++TM/-Caches-/com.apple.Xcode.502/SharedPrecompiledHeaders/testipod_Prefix-cwdputxcxpofoydkulngkdplqxbt/testipod_Prefix.pch -c /Users/sausalito/eth/testipod/WindowController.m -o /Users/sausalito/eth/testipod/build/testipod.build/Debug-iphonesimulator/testipod.build/Objects-normal/i386/WindowController.o

 In file included from /Users/sausalito/eth/testipod/Classes/test.h:10,
             from /Users/sausalito/eth/testipod/WindowController.m:10:
/Users/sausalito/eth/testipod/Classes/testlib.h:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'testlib'
 In file included from /Users/sausalito/eth/testipod/WindowController.m:10:
/Users/sausalito/eth/testipod/Classes/test.h:13: error: expected specifier-qualifier-list before 'testlib'

/Users/sausalito/eth/testipod/Classes/test.mm:13:0 /Users/sausalito/eth/testipod/Classes/test.mm:13: error: type of property 'testClass' does not match type of ivar 'testClass'

私は何を間違っていますか?? Cコンパイラを使用してヘッダーファイルをコンパイルしているようです。

メンバーを void* 型として宣言し、実装でキャストを使用すると、これを Objective-C クラスでラップできます。しかし、これは間違いなく最も快適な方法ではありません。

4

3 に答える 3

6

WindowController.m名前を に変更しますWindowController.mm

ファイル名が の場合、.m「翻訳単位」全体が ++ なしで ObjC にコンパイルされます。ただし、あなたのでは、C++ コードを含むtest.hものをインポートしています。testlib.hこれらの C++ コードは C では無効であるため、コンパイラ エラーが発生します。


ところで、

- (id)init {
 testClass = new testlib::Test(0);
 return self;
}

スーパーの init を呼び出す必要があります。

- (id)init {
  if ((self = [super init]))
     testClass = new testlib::Test(0);
  return self;
}

プロパティ

@property void* testClass;

Test* を返す必要があります。

@property(readonly,assign) testlib::Test* testClass;
于 2010-03-03T13:53:33.453 に答える
3

ファイルの名前を変更したくない場合は、ファイルの情報ウィンドウを開くことで、「.m」ファイルを ObjC++ としてコンパイルするよう XCode に明示的に指示することもできます (メイン XCode ウィンドウの左側のペインでファイル名をクリックし、青い「情報」ボタンを押します)。「ファイルの種類」を「sourcecode.cpp.objcpp」に変更します。

サンプル アプリの場合、ファイルの名前を変更するだけですが、大規模な名前変更を行いたくない既存のコードベースがある場合は、「ファイルの種類」設定が便利です。

于 2010-03-03T14:13:35.410 に答える
1

「Compile Source As」の下のビルド設定に移動して、Objective-c++ に変更し、ビルドを押します

于 2011-02-10T19:56:19.897 に答える