为 C++ 制作 Objective-C 包装器图书馆

发布于 2024-10-03 10:30:27 字数 622 浏览 0 评论 0原文

我正在尝试用 Objective-C 制作一个包装器,这样我就不必在库类之外编写 C++ 了。

库主文件是 LLAHProcessor.h .cpp

我的包装器是 LLAHProcessorWrapper.h .mm

它编译得很好,但是当我将 LLAHProcessorWrapper 添加到其他文件时类(比方说 UIView)作为成员变量,我收到数百个错误,例如:

#include <map> : Map no such a file or directory

在每个 C++ 类/结构中:

Expected specifier-qualifier list before ClassName

就像编译器无法识别 C++ 代码一样。

我想知道我在这里错过了什么。 这是否与我将其添加到 Xcode Target Properties: 中有关?

Other Link Flags : -lstdc++ -lz

或者也许我需要在这里添加新标志?

提前致谢

I am trying to make a wrapper in Objective-C so I don't have to write c++ outside the library classes.

The Library main file is LLAHProcessor.h .cpp

My Wrapper is 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:

#include <map> : Map no such a file or directory

and in every c++ class/struct:

Expected specifier-qualifier list before ClassName

Is like compiler is not recognizing c++ code.

I wonder what am I missing here.
Does it has to be something with the fact I added this to Xcode Target Properties: ?

Other Link Flags : -lstdc++ -lz

Or maybe I need to add new flags here?

Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

中性美 2024-10-10 10:30:27

您的问题是 .m 文件被编译为 C 而不是 C++。因此,当编译器在编译 .m 文件时遇到任何 C++,即使是在头文件中,它也会呕吐。

毫无疑问,您必须在头文件中放入一些 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

由于您从未在 .mm 文件之外取消引用 cppObject 的成员,因此您从不提供该结构的完整定义也没关系。

您可以分别在-init-deallocnewdelete 指针。您可以在 LLAHProcessorWrapper.mm 中包含完整的 C++ 类声明。

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.

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.

// 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.

You would new and delete the pointer in -init and -dealloc respectively. You would include the full C++ class declaration in LLAHProcessorWrapper.mm.

白芷 2024-10-10 10:30:27

您所需要做的就是像您所做的那样创建一个 .mm ,编译器应该处理所有事情。

需要注意的是,在 .h 文件中包含任何与 C++ 相关的内容是不安全的,因为它们可以/将由其他仅 Objective-C 的文件导入,然后一切都会崩溃。这里的主要问题是你不能直接将 C++ 类型定义为 Objective-C 包装类的实例变量,除非每个 .m 文件都被重命名为 Objective-C++ .mm< /代码> 文件。

解决方案是在头文件中将实例变量定义为void*,并从实现文件中通过类型转换来访问它们。最简单的解决方案是使用为您进行类型转换的私有属性来访问实例变量。

示例代码假设 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

All you need to do is to create a .mm as you have done, and the compiler should take care of everything.

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.

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.

Example code assuming Foo is a C++ class defined in Foo.h:

// 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
玻璃人 2024-10-10 10:30:27

在任何要引用 LLAHProcessorWrapper 的头文件 (.h) 中,使用前向类定义而不是导入,如下所示:

@class LLAHProcessorWrapper;
@interface SomeView : UIView {
  LLAHProcessorWrapper *wrapper;
}

并确保相应的实现文件有#include LLAHProcessorWrapper.h#import LLAHProcessorWrapper.h

任何包含 #include#import 标头的实现文件都必须以 .mm 作为后缀,如果 LLAHProcessorWrapper.h 或整个包含树中的任何其他内容 都具有任何 C++ 语法。这样,拥有一个 .mm 文件往往意味着代码库的很大一部分必须将其文件重命名为 .mm

In any header (.h) file in which you want to refer to LLAHProcessorWrapper, use forward class definitions instead of imports, like so:

@class LLAHProcessorWrapper;
@interface SomeView : UIView {
  LLAHProcessorWrapper *wrapper;
}

and make sure that the corresponding implementation file has #include LLAHProcessorWrapper.h or #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. 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文