xcode 为 C++ 库制作 Objective-C 包装器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4204239/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Making a Objective-C Wrapper for a C++ Library
提问by nacho4d
I am trying to make a wrapper in Objective-C so I don't have to write c++ outside the library classes.
我正在尝试在 Objective-C 中制作一个包装器,所以我不必在库类之外编写 C++。
The Library main file is LLAHProcessor.h .cpp
库主文件是 LLAHProcessor.h .cpp
My Wrapper is LLAHProcessorWrapper.h .mm
我的包装是 LLAHProcessorWrapper.h .mm
It compiles fine, but when I add LLAHProcessorWrapperto other class, (Lets say an UIView) as a member variable I get hundreds of errors, like:
它编译得很好,但是当我添加LLAHProcessorWrapper到其他类时(比如 UIView)作为成员变量,我得到了数百个错误,例如:
#include <map> : Map no such a file or directory
and in every c++ class/struct:
在每个 C++ 类/结构中:
Expected specifier-qualifier list before ClassName
Is like compiler is not recognizing c++ code.
就像编译器无法识别 C++ 代码一样。
I wonder what am I missing here. Does it has to be something with the fact I added this to Xcode Target Properties: ?
我想知道我在这里错过了什么。它是否必须与我将其添加到 Xcode Target Properties: 的事实有关?
Other Link Flags : -lstdc++ -lz
Or maybe I need to add new flags here?
或者我可能需要在这里添加新的标志?
Thanks in advance
提前致谢
采纳答案by JeremyP
Your problem is that .mfiles are compiled as C instead of C++. Thus when the compiler comes across any C++ even in a header file while compiling a .mfile, it will barf.
您的问题是.m文件被编译为 C 而不是 C++。因此,当编译器在编译文件时遇到任何 C++ 甚至在头文件中时.m,它都会barf。
No doubt you have to put some C++ in your header file because your Objective C object wraps a C++ object, but there are ways around this. One way would be to use a pointer to the C++ object and make use of the handy preprocessor define __cpluspluswhich is defined for C++ (and Objective-C++) but not for C (or Objective-C) e.g.
毫无疑问,您必须在头文件中放入一些 C++,因为您的 Objective C 对象包装了一个 C++ 对象,但有一些方法可以解决这个问题。一种方法是使用指向 C++ 对象的指针,并使用__cplusplus为 C++(和 Objective-C++)而不是为 C(或 Objective-C)定义的方便的预处理器定义,例如
// LLAHProcessorWrapper.h
#if defined __cplusplus
class MyCPPClass; // forward class declaration
#else
typedef struct MyCPPClass MyCPPClass; // forward struct declaration
#endif
@interface MyOCClass : NSObject
{
@private
MyCPPClass* cppObject;
}
// methods and properties
@end
Since you never dereference the members of the cppObject outside of the .mmfile it doesn't matter that you never provide a full definition for the struct.
由于您从未在.mm文件外部取消引用 cppObject 的成员,因此您从未提供该结构的完整定义并不重要。
You would newand deletethe pointer in -initand -deallocrespectively. You would include the full C++ class declaration in LLAHProcessorWrapper.mm.
你会new和delete指针分别在-init和-dealloc。您将在LLAHProcessorWrapper.mm.
回答by PeyloW
All you need to do is to create a .mmas you have done, and the compiler should take care of everything.
你需要做的就是.mm像你所做的那样创建一个,编译器应该负责一切。
The caveat being that it is not safe to have anything C++ related in the .hfiles, since they can/will be imported by other Objective-C only files, and then everything breaks down. The main problem here is that you can not define C++ types directly as instance variables for your Objective-C wrapper class, unless every single .mfile is renamed as a Objective-C++ .mmfile.
需要注意的是,在.h文件中包含任何与 C++ 相关的内容是不安全的,因为它们可以/将被其他仅限 Objective-C 的文件导入,然后一切都会崩溃。这里的主要问题是您不能直接将 C++ 类型定义为 Objective-C 包装类的实例变量,除非每个.m文件都被重命名为 Objective-C++.mm文件。
The solution is to define the instance variables as void*in the header file, and access them with type casting from the implementation file. Easiest solution for this would be to access the instance variable using a private property that to the typecast for you.
解决方案是void*在头文件中定义实例变量,并从实现文件中通过类型转换访问它们。最简单的解决方案是使用私有属性访问实例变量,该属性为您进行类型转换。
Example code assuming Foois a C++ class defined in Foo.h:
示例代码假设Foo是在Foo.h以下位置定义的 C++ 类:
// FooWrapper.h
#import <Foundation/Foundation.h>
@interface FooWrapper : NSObject {
@private
void* foo;
}
// Actual wrapper API for Foo…
@end
// FooWrapper.mm
#import "FooWrapper.h"
#include <map>
#include "Foo.h"
@interface FooWrapper ()
@property(nonatomic, assign) Foo* foo;
@end
@implementation FooWrapper
-(Foo*)foo {
return (Foo*)foo;
}
-(void)setFoo:(Foo*)aFoo {
foo = (void*)aFoo;
}
// Implementation of actual API for Foo…
@end
回答by Josh Bleecher Snyder
In any header (.h) file in which you want to refer to LLAHProcessorWrapper, use forward class definitions instead of imports, like so:
在.h您要引用的任何头 ( ) 文件中LLAHProcessorWrapper,使用前向类定义而不是导入,如下所示:
@class LLAHProcessorWrapper;
@interface SomeView : UIView {
LLAHProcessorWrapper *wrapper;
}
and make sure that the corresponding implementation file has #include LLAHProcessorWrapper.hor #import LLAHProcessorWrapper.h.
并确保相应的实现文件具有#include LLAHProcessorWrapper.h或#import LLAHProcessorWrapper.h。
Any implementation file in which you #includeor #importyour header must have .mmas its suffix if LLAHProcessorWrapper.hor anything else in the entire include treehas any C++ syntax at all. In this way, having one .mmfile has a tendency to mean that huge portions of a codebase must have their files renamed to .mm.
任何执行文件,在其中您#include或#import您的标题必须有.mm它的后缀,如果LLAHProcessorWrapper.h还是别的整个包括树拥有所有任何C ++的语法。通过这种方式,拥有一个.mm文件往往意味着代码库的很大一部分必须将它们的文件重命名为.mm.

