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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 19:56:02  来源:igfitidea点击:

Making a Objective-C Wrapper for a C++ Library

iphonec++objective-cxcodestl

提问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.

你会newdelete指针分别在-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.