c++ - 从 .cpp 文件调用 .mm 函数的链接器错误

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

我已将一个 obj-c 类(.mm 和 2 个 header )添加到我当前的 Xcode 4.6 项目中。一个头文件具有调用 obj-c 类的原型(prototype),另一个定义了 .mm 类。这是它的样子。

我的接口(interface).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 文件添加到构建阶段中的目标,并将标题位置添加到build设置中的标题搜索路径。

当我在我的 .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++ 视为“具有 C++ 类型变量和调用 C++ 代码能力的 Objective-C”,但不是作为“声明 C++ 类型的替代语法” ”

Caveat Emptor!:这极大地简化了将 Objective-C 对象有意义地包装在 C++ 对象中所涉及的内容。 C++ 的按值/按引用语义与 Objective-C 的截然不同,如果 C++ 对象按值传递(即通过一个复制构造函数)等。我提供示例只是为了说明为什么您尝试的方法不起作用,而不是将 Objective-C 对象包装在 C++ 对象中的某种通用代码。

关于c++ - 从 .cpp 文件调用 .mm 函数的链接器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19007376/

相关文章:

c++ - 为 OpenCV 编译 MATLAB 绑定(bind)

c++ - 类成员和继承

iphone - 控制台错误 : UICollectionView must be initialized with a non-nil layout parameter

c++ - 使用不同优化级别编译的不同翻译单元中的模板实例化

c++ - 单链表的时间复杂度

ios - 哪个是显示链接,UITextView/UILabel中的热词的最佳解决方案?

ios - 自定义 UITextField 委托(delegate)设置为自启动无限循环

c++ - 当我将项目编译为静态库( undefined reference )时,我可以在我的代码中使用 QImage 吗?

c - 数学库中的文字常量与变量

c++ - 设置不同断点输出不同