我在当前的Xcode 4.6项目中添加了一个obj-c类(.mm和2个标题)。一个头文件具有调用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文件添加到目标,并在构建设置中将标题位置添加到标题搜索路径。
当我在.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 :(得分:1)
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 ++类型的替代语法” 。“
警告Emptor!:这大大过分简化了在C ++对象中有意义地包装Objective-C对象所涉及的内容。 C ++的by-value / by-reference语义与Objective-C的完全不同,如果C ++对象通过值传递,那么像这样的天真实现会遇到各种各样的问题(即通过复制构造函数)等。我提供的示例只是为了说明为什么你的尝试不起作用,而不是用于在C ++对象中包装Objective-C对象的某种通用代码。