如何在 Obj-C 中使用 C++ 静态库?
How do I use a C++ static library in Obj-C?
我有一个 C++ 静态库:.a
文件和 staticLibrary.h
文件。
在.h文件中,有一个class我要访问:
typedef enum
{
eStaticLibOperationUnknown = 0
eStaticLibOperationSystemCheck = 1
} enumStaticLibOperation;
typedef enum
{
eStaticLibResultUnknown = 0,
eStaticLibResultNullParameter = 4,
eStaticLibResultWrongParameter = 5
} enumStaticLibResult;
typedef std::function<void(void)> typeCallBack;
class classResultHelper
{
blah blah
};
class staticLibrary
{
public:
staticLibrary(typeCallBack, const char*);
void requestOperation(const char*, size_t);
void requestOperation(enumStaticLibOperation, const char*, size_t);
enumStaticLibResult getResult(char**, size_t*);
};
我在 viewController.m 文件的顶部使用了 #import "staticLibrary.h"
。这引发了一个错误,因为它认为 C++ 是外来的。然后我将 viewController 更改为 .mm 扩展名,使文件成为 Objective-C++ 并删除了错误。
但是当我尝试在 viewDidLoad 中 运行 staticLibrary* sL = [[staticLibrary alloc] init];
时,我在右侧的第二个 staticLibrary 处出错。它说 "receiver type is not an objective-c class"。我做错了什么?
在查看使用静态库的文档时,它说:
1.1. new staticLibrary(callback, “en”);
1.2. requestOperation(“enumSystemcheck”, NULL, 0);
1.3. callback();
1.4. getResult(... , ...);"
我相信这是 Java (?),第一行是使用这些参数创建 staticLibrary 的实例。在 objective-C 中我该怎么做?
示例中的代码不是 Java,而是 C++。 ObjC++ 意味着你可以在一行中混合用 C++ 或 ObjC 编写的语句,这并不意味着你可以像使用 ObjC objects 一样使用 C++ objects,或者使用 ObjC 语法。
人们通常做的只是在 .mm 文件本身中包含 C++ headers 和编写 C++ 代码,而不会在 header 中放入任何内容。编写一个 ObjC class 来包装您想要的 C++ 库部分。所以在你的例子中,那会是这样的:
JCRStaticLibrary.h
@interface JCRStaticLibrary : NSObject
-(instancetype) initWithCallback: (void(^)(void))inObjCCallback;
-(void) requestOperation: (NSString*)what withBuffer: (void*)buf size: (int)theSize;
@end
JCRStaticLibrary.mm
#import "JCRStaticLibrary.h"
#include "staticLibrary.h"
@interface JCRStaticLibrary ()
{
staticLibrary *_cppStaticLibrary;
}
@end
@implementation JCRStaticLibrary
-(instancetype) initWithCallback: (void(^)(void))inObjCCallback
{
self = [super init];
if( self )
{
_staticLibrary = new staticLibrary( inObjCCallback, "en"); // ObjC++ knows how to turn an ObjC block into a C++ lambda.
// Under the hood it generates code like:
// _staticLibrary = new staticLibrary( [inObjCCallback](){ inObjCCallback(); }, "en");
// Where the [inObjCCallback](){} part is how C++ does lambdas, its equivalent to blocks.
// I.e. it's roughly analogous to ObjC's ^(){}.
}
}
-(void) dealloc
{
delete _staticLibrary;
}
-(void) requestOperation: (NSString*)what withBuffer: (void*)buf size: (int)theSize
{
_staticLibrary->requestOperation( [what UTF8String], buf, theSize );
}
@end
类似的东西。我不知道你的情况下 requestOperation 的参数实际上是什么,所以我只是做了一个有根据的猜测。
除了将 ObjC 块传递给 -initWithCallback:
,您还可以编写自己的 lambda 并将其作为方法,即:
-(instancetype) init
{
__weak JCRStaticLibrary *weakSelf = self; // Avoid retain circle.
_staticLibrary = new staticLibrary( [weakSelf](){ [weakSelf doCallbackThing]; }, "en"); // ObjC++ knows how to turn an ObjC block into a C++ lambda.
}
-(void) doCallbackThing
{
// Do whatever the callback should do here.
}
这实际上取决于每次创建此类型的 object 时回调是否更改(例如,如果 JCRStaticLibrary object 表示通过网络发送的命令)或来自一个小集合一遍又一遍地使用的命令(例如,您收到一个视频帧并对其应用过滤器,然后将其交给另一个 object,因此您实际上只有一个回调)。在前一种情况下你想保留块,在后者中,每个过滤器 有一个 subclass 可能 更有意义(除非你想在过滤器之间切换 on-the-fly).
我有一个 C++ 静态库:.a
文件和 staticLibrary.h
文件。
在.h文件中,有一个class我要访问:
typedef enum
{
eStaticLibOperationUnknown = 0
eStaticLibOperationSystemCheck = 1
} enumStaticLibOperation;
typedef enum
{
eStaticLibResultUnknown = 0,
eStaticLibResultNullParameter = 4,
eStaticLibResultWrongParameter = 5
} enumStaticLibResult;
typedef std::function<void(void)> typeCallBack;
class classResultHelper
{
blah blah
};
class staticLibrary
{
public:
staticLibrary(typeCallBack, const char*);
void requestOperation(const char*, size_t);
void requestOperation(enumStaticLibOperation, const char*, size_t);
enumStaticLibResult getResult(char**, size_t*);
};
我在 viewController.m 文件的顶部使用了 #import "staticLibrary.h"
。这引发了一个错误,因为它认为 C++ 是外来的。然后我将 viewController 更改为 .mm 扩展名,使文件成为 Objective-C++ 并删除了错误。
但是当我尝试在 viewDidLoad 中 运行 staticLibrary* sL = [[staticLibrary alloc] init];
时,我在右侧的第二个 staticLibrary 处出错。它说 "receiver type is not an objective-c class"。我做错了什么?
在查看使用静态库的文档时,它说:
1.1. new staticLibrary(callback, “en”);
1.2. requestOperation(“enumSystemcheck”, NULL, 0);
1.3. callback();
1.4. getResult(... , ...);"
我相信这是 Java (?),第一行是使用这些参数创建 staticLibrary 的实例。在 objective-C 中我该怎么做?
示例中的代码不是 Java,而是 C++。 ObjC++ 意味着你可以在一行中混合用 C++ 或 ObjC 编写的语句,这并不意味着你可以像使用 ObjC objects 一样使用 C++ objects,或者使用 ObjC 语法。
人们通常做的只是在 .mm 文件本身中包含 C++ headers 和编写 C++ 代码,而不会在 header 中放入任何内容。编写一个 ObjC class 来包装您想要的 C++ 库部分。所以在你的例子中,那会是这样的:
JCRStaticLibrary.h
@interface JCRStaticLibrary : NSObject
-(instancetype) initWithCallback: (void(^)(void))inObjCCallback;
-(void) requestOperation: (NSString*)what withBuffer: (void*)buf size: (int)theSize;
@end
JCRStaticLibrary.mm
#import "JCRStaticLibrary.h"
#include "staticLibrary.h"
@interface JCRStaticLibrary ()
{
staticLibrary *_cppStaticLibrary;
}
@end
@implementation JCRStaticLibrary
-(instancetype) initWithCallback: (void(^)(void))inObjCCallback
{
self = [super init];
if( self )
{
_staticLibrary = new staticLibrary( inObjCCallback, "en"); // ObjC++ knows how to turn an ObjC block into a C++ lambda.
// Under the hood it generates code like:
// _staticLibrary = new staticLibrary( [inObjCCallback](){ inObjCCallback(); }, "en");
// Where the [inObjCCallback](){} part is how C++ does lambdas, its equivalent to blocks.
// I.e. it's roughly analogous to ObjC's ^(){}.
}
}
-(void) dealloc
{
delete _staticLibrary;
}
-(void) requestOperation: (NSString*)what withBuffer: (void*)buf size: (int)theSize
{
_staticLibrary->requestOperation( [what UTF8String], buf, theSize );
}
@end
类似的东西。我不知道你的情况下 requestOperation 的参数实际上是什么,所以我只是做了一个有根据的猜测。
除了将 ObjC 块传递给 -initWithCallback:
,您还可以编写自己的 lambda 并将其作为方法,即:
-(instancetype) init
{
__weak JCRStaticLibrary *weakSelf = self; // Avoid retain circle.
_staticLibrary = new staticLibrary( [weakSelf](){ [weakSelf doCallbackThing]; }, "en"); // ObjC++ knows how to turn an ObjC block into a C++ lambda.
}
-(void) doCallbackThing
{
// Do whatever the callback should do here.
}
这实际上取决于每次创建此类型的 object 时回调是否更改(例如,如果 JCRStaticLibrary object 表示通过网络发送的命令)或来自一个小集合一遍又一遍地使用的命令(例如,您收到一个视频帧并对其应用过滤器,然后将其交给另一个 object,因此您实际上只有一个回调)。在前一种情况下你想保留块,在后者中,每个过滤器 有一个 subclass 可能 更有意义(除非你想在过滤器之间切换 on-the-fly).