简体   繁体   English

为C ++库制作Objective-C包装器

[英]Making a Objective-C Wrapper for a C++ Library

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 Library主文件是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 提前致谢

Your problem is that .m files are compiled as C instead of C++. 您的问题是.m文件被编译为C而不是C ++。 Thus when the compiler comes across any C++ even in a header file while compiling a .m file, it will barf. 因此,当编译器在编译.m文件时,即使在头文件中遇到任何C ++,它也会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. 毫无疑问,你必须在头文件中加入一些C ++,因为Objective C对象包装了一个C ++对象,但是有很多方法可以解决这个问题。 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) eg 一种方法是使用指向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文件之外的.mm成员,因此您永远不会为结构提供完整定义。

You would new and delete the pointer in -init and -dealloc respectively. 您将new并分别delete -init-dealloc的指针。 You would include the full C++ class declaration in LLAHProcessorWrapper.mm . 您将在LLAHProcessorWrapper.mm包含完整的C ++类声明。

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. 需要注意的是,在.h文件中有任何与C ++相关的东西是不安全的,因为它们可以/将被其他仅使用Objective-C的文件导入,然后一切都会崩溃。 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. 这里的主要问题是你不能直接将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. 解决方案是在头文件中将实例变量定义为void* ,并从实现文件中使用类型转换来访问它们。 Easiest solution for this would be to access the instance variable using a private property that to the typecast for you. 最简单的解决方案是使用为您进行类型转换的私有属性来访问实例变量。

Example code assuming Foo is a C++ class defined in Foo.h : 假设FooFoo.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

In any header ( .h ) file in which you want to refer to LLAHProcessorWrapper , use forward class definitions instead of imports, like so: 在任何要引用LLAHProcessorWrapper头文件( .h )中,使用正向类定义而不是导入,如下所示:

@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 tree has any C++ syntax at all. 如果LLAHProcessorWrapper.h整个包含树中的任何其他内容都具有任何C ++语法,则#include#import标头的任何实现文件都必须具有.mm作为其后缀。 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 . 这样,有一个.mm文件倾向于意味着代码库的大部分必须将其文件重命名为.mm

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

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