简体   繁体   English

Xcode:从Objective-C项目引用C ++项目

[英]Xcode: Referencing C++ project from Objective-C project

I'm beginning to tear my hair out over this, so it's time to post here! 我开始为此扯头发,所以是时候在这里发布了!

I have a C++ project in XCode, built as a Command Line Tool. 我在XCode中有一个C ++项目,它是作为命令行工具构建的。 All .cpp files have been renamed as .mm, there is one .hh and a few .h headers. 所有.cpp文件都已重命名为.mm,其中有一个.hh和几个.h标头。 I've specified 'Compile Sources As -> Objective-C++' in Build Settings. 我在构建设置中指定了“将源编译为-> Objective-C ++”。

I have another XCode project for an iOS app. 我还有一个适用于iOS应用程序的XCode项目。 This is set to 'Compile Sources As -> According to File Type'. 设置为“将源编译为->根据文件类型”。 I can't set it to compile everything as Objective-C++ since some parts of the project won't compile as Obj-C++. 我无法将其设置为将所有内容编译为Objective-C ++,因为项目的某些部分不会编译为Obj-C ++。

There is one class in the iOS app where I wish to utilise my C++ project, and it consists of files MyClass.hh, MyClass.mm; 我希望使用我的C ++项目在iOS应用中有一个类,它由文件MyClass.hh,MyClass.mm组成; they were simply .h and .m but I renamed them in the hope of remedying this problem. 它们分别是.h和.m,但我改名了它们,以期解决此问题。

I dragged my cpp project into the iOS project. 我将cpp项目拖到iOS项目中。 I then added a Target Dependency in the iOS Build Phases to point to the cpp CLI application. 然后,我在iOS构建阶段中添加了目标依赖关系,以指向cpp CLI应用程序。

In MyClass.hh I have 在MyClass.hh中

#include "../path/to/CppProject/ImportAll.h"

..which is a header file that successively 'include's all headers from the cpp project. ..这是一个头文件,该文件连续“包含” cpp项目中的所有头。 I then go about my business, creating one property within MyClass.hh which is a pointer to a cpp object, and various references within MyClass.mm to cpp classes. 然后,我着手开展业务,在MyClass.hh中创建一个属性,该属性是指向cpp对象的指针,并在MyClass.mm中创建对cpp类的各种引用。

The darn thing just won't compile though - I get a ton of messages relating to my cpp classes like this: 该死的东西虽然无法编译-我收到大量与我的cpp类有关的消息,如下所示:

MyCPPFile.h:10: error: expected '=', ',', ';', 'asm' or '__attribute__' before '<' token

Is the compiler not recognising that MyClass.hh is Objective-C++ not Objective-C? 编译器是否没有意识到MyClass.hh是Objective-C ++而不是Objective-C? Should I have a target dependency which is a library instead of pointing to this CLI app, perhaps? 我是否应该有一个目标依赖项,它是一个库,而不是指向此CLI应用程序?

I've googled around for a while trying to solve the problem. 我已经在Google周围搜索了一段时间,以解决问题。 I've seen references to people using 我看到过有人使用

#ifdef __cplusplus

or else having to rename files to .mm to get things working, but in other cases people simply say they drag and drop projects across with no issues. 否则必须将文件重命名为.mm才能正常工作,但在其他情况下,人们只是说他们拖放项目就没有问题。

Can someone please enlighten me, and explain what key steps I should be performing to make this work? 有人可以启发我,并说明为完成这项工作我应该执行哪些关键步骤? I'd be very grateful! 我将非常感谢! Thank you. 谢谢。

Thanks to everyone who gave me suggestions. 感谢所有给我建议的人。

Having created my projects anew from scratch, I fiddled and logic-ed my way to the solution. 从头开始重新创建项目后,我弄弄了逻辑,并找到了解决方案的方法。 Note that - at least in my case - no use of #ifdef __cplusplus was required, nor any other preprocessor directive. 请注意-至少就我而言-不需要使用#ifdef __cplusplus,也不需要任何其他预处理程序指令。 Only file suffix changing is essential (as detailed below). 仅更改文件后缀是必不可少的(如下所述)。

Here's the process: 过程如下:

Create C++ Static Library and Include/Link with Objective-C Library (eg iOS app) in XCode 4 : 在XCode 4中创建C ++静态库并使用Objective-C库(例如iOS应用)进行包含/链接

  • In XCode 4 create a New Project of type Cocoa Touch Static Library. 在XCode 4中,创建一个Cocoa Touch Static Library类型的New Project。 Hereafter we shall refer to this project as 'CProj'. 此后,我们将此项目称为“ CProj”。
  • In CProj workspace create/import as many C++ classes as required. 在CProj工作区中,根据需要创建/导入尽可能多的C ++类。 No special suffix for filenames is necessary - all my files are .h and .cpp. 文件名不需要特殊的后缀-我的所有文件都是.h和.cpp。
  • In XCode create/open any Objective-C project eg iOS app. 在XCode中创建/打开任何Objective-C项目,例如iOS应用。 Hereafter we shall refer to this project as 'ObjProj'. 此后,我们将该项目称为“ ObjProj”。
  • Find CProj.xcodeproj in Finder (typically /Documents/CProj/CProj.xcodeproj), drag it onto the visible ObjProj project icon at the top of your XCode Project Navigator (visible file/folder hierarchy on left side in XCode). 在Finder中查找CProj.xcodeproj(通常为/Documents/CProj/CProj.xcodeproj),将其拖到XCode Project Navigator顶部(XCode左侧的可见文件/文件夹层次结构)的可见ObjProj项目图标上。 This now places CProj as a nested project within ObjProj. 现在,这会将CProj放置为ObjProj中的嵌套项目。
  • Left click ObjProj project icon in Project Navigator, a new pane emerges to the right, left click Build Phases in this pane. 左键单击Project Navigator中的ObjProj项目图标,右侧将出现一个新窗格,左键单击此窗格中的Build Phases。
  • Under Target Dependencies click '+' icon and select CProj library icon below listed CProj project. 在“目标依赖项”下,单击“ +”图标,然后选择列出的CProj项目下面的CProj库图标。 Click OK. 单击确定。
  • Under Link Binary With Libraries click '+' icon and select CProj library icon from within Workspace collapsible folder at top of window presented. 在“使用库链接二进制文件”下,单击“ +”图标,然后从显示的窗口顶部的Workspace可折叠文件夹中选择CProj库图标。

File Renaming Rules 文件重命名规则

  • Where including a CProj header in ObjProj, use path backtracking to identify import, eg #include "../../MyProj/MyImport.h" to step 2 dirs backwards then step into MyProj folder. 如果在ObjProj中包含CProj标头,则使用路径回溯来识别导入,例如,将#include“ ../../MyProj/MyImport.h”向前倒2步,然后进入MyProj文件夹。

  • Any ObjProj implementation file including a CProj header must be renamed from .m to .mm . 任何包含CProj标头的ObjProj实现文件都必须从.m重命名为.mm。 Any ObjProj header file including a CProj header must be renamed from .h to .hh . 任何包含CProj头的ObjProj头文件都必须从.h重命名为.hh。

  • Any ObjProj file including a file whose suffix is now .hh (consequence of step above) must be renamed in the same manner. 任何ObjProj文件,包括后缀现在为.hh(上述步骤的结果)的文件,都必须以相同的方式重命名。

An example: Consider you have files Ah, Am, Bh, BmAm imports Bh, and Bh includes one or more CProj headers. 一个示例:考虑您有文件Ah,Am,Bh,BmAm导入Bh,并且Bh包含一个或多个CProj标头。 Bm includes type references, using CProj classes included via Bh . Bm使用通过Bh包含的CProj类来包括类型引用。 First renaming is Bh -> B.hh since it contains includes. 首先重命名为Bh-> B.hh,因为它包含include。 Then Bm -> B.mm since it contains type references to CProj (no includes necessary since Bh has already done them). 然后Bm-> B.mm,因为它包含对CProj的类型引用(由于Bh已经完成了对它们的引用,因此不需要包含)。 Then Am -> A.mm since Am which contained an include for Bh now has an include for the renamed file, B.hh . 然后Am-> A.mm,因为Am包含了Bh的包含内容,现在有了重命名文件B.hh的包含内容。

PS Note that the C++ library doesn't like to auto-rebuild when it should - I often have to 'Clean' then 'Build' in ObjProj after updating CProj from within it. PS注意,C ++库不应该在需要时自动重建-我经常需要在ObjProj中从内部更新CProj之后先“清理”然后“构建”。

It sounds like the crux of your problem is this: 听起来您问题的症结在于:

Is the compiler not recognising that MyClass.hh is Objective-C++ not Objective-C? 编译器是否没有意识到MyClass.hh是Objective-C ++而不是Objective-C?

The compiler is not recognizing that MyClass.hh is Objective-C++ code. 编译器无法识别MyClass.hh是Objective-C ++代码。 Or any other code; 或任何其他代码; the compiler never sees MyClass.hh (in all likelyhood). 编译器永远不会看到MyClass.hh。

By convention, header files are never passed to the compiler by default. 按照约定,默认情况下,头文件永远不会传递给编译器。 Only the source files (.cpp, .m, et cetera) are -- the preprocessor that is run on those files results a translation unit that contains the original source file plus all the included headers and resolved macros. 只有源文件(.cpp,.m等)才是-在这些文件上运行的预处理器会生成包含原始源文件以及所有包含的标头和已解析宏的转换单元。

So the problem is that you probably have a .mm source file that imports MyClass.hh, which in turn includes the C++ header file. 因此,问题在于您可能有一个导入MyClass.hh的.mm源文件,而该文件又包含C ++头文件。 But the compiler is trying to compile the resulting translation unit as Objective-C++ and encountering some C++-specific stuff in that header. 但是编译器试图将生成的翻译单元编译为Objective-C ++,并在该标头中遇到一些C ++特定的东西。 In fact, I suspect that this problem has nothing at all to do with the additional target dependencies and such that you've got set up: I think you could reproduce it minimally with a very simple Objective-C++ application that includes the header. 实际上,我怀疑这个问题与其他目标依赖关系完全无关,因此您已经设置好了:我认为您可以使用包含标头的非常简单的Objective-C ++应用程序以最少的方式重现该问题。 You should try that and see, it will either confirm my theory (after all I'm just speculating since you haven't shown enough source for me to know for sure) or indicate that the problem is elsewhere. 您应该尝试一下,看看它会证实我的理论(毕竟我只是在推测,因为您没有提供足够的资料让我确定),或者表明问题出在其他地方。

The solution is probably to use preprocessor guards like #ifdef __cplusplus (there's a useful catalog of predefined symbols here ) to hide the C++-specific code from the Objective-C++ compiler (or the other way around in some cases). 该解决方案可能是使用预处理器后卫像#ifdef __cplusplus (有预定义符号的一个有用的目录, 在这里 )隐藏C ++ -来自特定代码的Objective-C ++编译器(或在某些情况下,周围的其他方法)。 Note that this may be difficult to impossible to do based on the actual content of the header. 请注意,根据标头的实际内容,这可能很难或不可能做到。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM