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 LLAHProcessorWrapper
to 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 .m
files are compiled as C instead of C++. Thus when the compiler comes across any C++ even in a header file while compiling a .m
file, 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 __cplusplus
which 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 .mm
file it doesn't matter that you never provide a full definition for the struct.
由于您从未在.mm
文件外部取消引用 cppObject 的成员,因此您从未提供该结构的完整定义并不重要。
You would new
and delete
the pointer in -init
and -dealloc
respectively. 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 .mm
as 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 .h
files, 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 .m
file is renamed as a Objective-C++ .mm
file.
需要注意的是,在.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 Foo
is 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.h
or #import LLAHProcessorWrapper.h
.
并确保相应的实现文件具有#include LLAHProcessorWrapper.h
或#import LLAHProcessorWrapper.h
。
Any implementation file in which you #include
or #import
your header must have .mm
as its suffix if LLAHProcessorWrapper.h
or anything else in the entire include treehas any C++ syntax at all. In this way, having one .mm
file 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
.