链接器错误从.cpp文件调用.mm函数

时间:2013-09-25 14:13:44

标签: c++ objective-c linker osx-lion xcode4.6

我在当前的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编程还是有点新鲜。任何帮助表示赞赏。

1 个答案:

答案 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对象的某种通用代码。