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

后端 未结 3 477
囚心锁ツ
囚心锁ツ 2020-12-29 15:42

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

相关标签:
3条回答
  • 2020-12-29 16:00

    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.

    0 讨论(0)
  • 2020-12-29 16:05

    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
    
    0 讨论(0)
  • 2020-12-29 16:06

    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.

    0 讨论(0)
提交回复
热议问题