Ошибка компоновщика при вызове функции .mm из файла .cpp

Я добавил класс 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. Любая помощь приветствуется.

0

Решение

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 ++.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]