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

Linker error calling .mm function from .cpp file

本文关键字:链接 出错 cpp 函数 文件 调用 mm      更新时间:2023-10-16

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

我的界面.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编程仍然有点陌生。任何帮助,不胜感激。

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

其他文件.cpp

void someOtherFunction()
{
    WrappedMyLaunchClass x;
    x.LaunchApp("foobar");
}

总之,你高估了C++和Objective-C++的互操作性。 你可以将 Objective-C++ 视为"Objective-C,增加了具有C++类型变量和调用C++代码的能力",但不是"声明C++类型的替代语法"。

警告Emptor!:这大大简化了将Objective-C对象有意义地包装在C++对象中所涉及的内容。 C++的按值/按引用语义与Objective-C的语义截然不同,如果C++对象通过值传递(即通过复制构造函数(等,像这样的天真实现会遇到各种问题。我提供这个例子只是为了说明为什么你尝试的东西不起作用,而不是作为某种通用代码,将Objective-C对象包装在C++对象中。