Я добавил класс obj-c (.mm и 2 заголовка) в мой текущий проект Xcode 4.6. Один заголовочный файл имеет прототип для вызова класса obj-c, а другой определяет класс .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-файл в Target на этапах сборки и расположение заголовка к путям поиска по заголовкам в настройках сборки.
Когда я включаю заголовочный файл в мой файл .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. Любая помощь приветствуется.
Objective-C ++ не взаимодействует таким образом. -(BOOL)LaunchApp:(CAtlString)exePath
объявляет метод экземпляра в классе Objective-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 ++ как о «Objective-C с добавлением возможности иметь переменные типов C ++ и способности вызывать код C ++», но не как «альтернативный синтаксис для объявления типов C ++».
Пусть покупатель будет бдителен!Это существенно упрощает то, что могло бы быть использовано для осмысленного переноса объекта Objective-C в объект C ++. Семантика по значению / по ссылке в C ++ коренным образом отличается от Objective-C и такой простой реализации, как эта, и столкнется с множеством проблем, если объект C ++ будет когда-либо передаваться по значению (т. е. через конструктор копирования) и т. д. Я приведу пример только для того, чтобы показать, почему вы пытались Это не какой-то универсальный код для обертывания объектов Objective-C в объектах C ++.
Других решений пока нет …