【发布时间】:2020-07-06 01:30:00
【问题描述】:
有没有办法将 Objective-C 类包装在 C struct 中,以使 struct 的名称反映该类的名称?理想情况下,我希望模仿使用 extern "C" in C++ as shown here 的行为,而不是必须指向 TestObject 类型的结构的成员,如下面的简单程序所示。
将 Objective-C 类包装到 C 结构中
testobject.m
#ifndef testobject_h
#define testobject_h
#ifdef __OBJC__
@interface TestObject : NSObject
- (void) printHello;
@end
#endif
typedef struct TestObjectC TestObjectC;
TestObjectC* newTestObject(void);
void TestObject_printHello(TestObjectC *t);
#endif /* testobject_h */
testobject.m
#import <Foundation/Foundation.h>
#import "testobject.h"
@implementation TestObject
- (void)printHello
{
printf("HELLO!\n");
}
@end
typedef struct TestObject_t
{
TestObject *testObject;
}TestObjectC;
TestObjectC* newTestObject(void)
{
TestObjectC *t = malloc(sizeof(TestObjectC));
t->testObject = [TestObject new];
return t;
}
void TestObject_printHello(TestObjectC* t)
{
[t->testObject printHello];
}
main.c
#include "testobject.h"
int main(int argc, const char * argv[])
{
TestObjectC *t = newTestObject();
TestObject_printHello(t);
return 0;
}
将 C++ 类包装成 C 结构
TestClass.h
#ifndef __TESTCLASS_H
#define __TESTCLASS_H
class TestClass
{
public:
void printHello(void);
};
#endif
TestClass.cc
#include "TestClass.h"
void TestClass::printHello(void)
{
printf("HELLO!\n");
}
MyWrapper.h
#ifndef __MYWRAPPER_H
#define __MYWRAPPER_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct TestClass TestClass;
TestClass* newTestClass();
void TestClass_printHello(TestClass* v);
void deleteTestClass(TestClass* v);
#ifdef __cplusplus
}
#endif
#endif
MyWrapper.cc
#include "TestClass.h"
#include "MyWrapper.h"
extern "C"
{
TestClass* newTestClass()
{
return new TestClass();
}
void TestClass_int_set(TestClass* v, int i)
{
v->printHello();
}
void deleteTestClass(TestClass* v)
{
delete v;
}
}
C 程序
#include "MyWrapper.h"
#include <stdio.h>
int main(int argc, char* argv[])
{
struct TestClass* c = newTestClass();
TestClass_printHello(c);
deleteTestClass(c);
}
【问题讨论】:
-
一个 ObjC 对象是一个 C 结构。
typedef struct objc_object { Class isa; } *id。这就是 CoreFoundation 的工作方式,允许您透明地将 ObjC 对象传递给 CoreFoundation C 函数。特别注意“免费桥接”。 developer.apple.com/library/archive/documentation/General/… -
另外,不要忘记内存管理。您当前的解决方案似乎违反了 ARC 规则,并且您没有在任何地方发送
-release,所以我看不到 TestObject 是如何被释放的。我建议花一些时间在opensource.apple.com/source/objc4/objc4-779.1/runtime,尤其是objc.h。 -
这个例子有点臃肿,我已经放弃了
init和dealloc来获得一些接近简洁的东西。假设这是一个单独的问题,但是是的,ARC 不会处于活动状态 -
请参阅github.com/iosptl/ios7ptl/blob/master/ch24-DeepObjC/Runtime/… 以获取完全从 C 管理 ObjC 的示例。我不太清楚您在这里尝试使用包装器实现什么。 ObjC 运行时具有完整的 C API。 (myMsgSend 展示了如何手动实现 msg_send,您通常不需要它)
-
@RobNapier 抱歉,在我跳跃之前没有看。 sdk 的入口点只是一个
main.c文件,我认真地认为可以将其更改为main.m以使用 objc 类公开
标签: c objective-c class struct wrapper