I am writing an Objective-C class but it uses an API written in C. This is mostly fine as mixing C calls with Objective-C calls causes few problems.
我正在编写一个Objective-C类,但它使用了用C编写的API。这很好,因为使用Objective-C调用混合C调用几乎没有问题。
However one of the API call requires a call back method (example):
但是,其中一个API调用需要回调方法(示例):
success = CFHostSetClient(host, MyCFHostClientCallBack, &context);
Where MyCFHostClientCallBack
is a C function defined like this:
MyCFHostClientCallBack是一个C函数定义如下:
static void MyCFHostClientCallBack(CFHostRef host, CFHostInfoType typeInfo, const CFStreamError *error, void *info);
- Can/How do I call an Objective-C method in place of this?
- 可以/如何使用Objective-C方法代替此方法?
- Can/Should I mix C functions with my Objective-C calls?
- 可以/我应该将C函数与Objective-C调用混合使用吗?
- How do I mix C functions with Objective-C methods?
- 如何将C函数与Objective-C方法混合使用?
4 个解决方案
#1
48
Mixing C and Objective-C methods and function is possible, here is a simple example that uses the SQLite API within an iPhone App: (course site)
可以混合使用C和Objective-C方法和函数,这是一个在iPhone App中使用SQLite API的简单示例:(课程网站)
Download the Zip file (09_MySQLiteTableView.zip)
下载Zip文件(09_MySQLiteTableView.zip)
C functions need to be declared outside of the @implementation
in an Objective-C (.m) file.
需要在Objective-C(.m)文件中的@implementation之外声明C函数。
int MyCFunction(int num, void *data)
{
//code here...
}
@implementation
- (void)MyObjectiveCMethod:(int)number withData:(NSData *)data
{
//code here
}
@end
Because the C function is outside of the @implementation
it cannot call methods like
因为C函数在@implementation之外,所以它不能调用像
[self doSomething]
and has no access to ivars.
并且无法访问ivars。
This can be worked around as long as the call-back function takes a userInfo
or context
type parameter, normally of type void*
. This can be used to send any Objective-C object to the C function.
只要回调函数采用userInfo或context类型参数(通常为void *类型),就可以解决此问题。这可用于将任何Objective-C对象发送到C函数。
As in the sample code, this can be manipulated with normal Objective-C operations.
与示例代码中一样,可以使用正常的Objective-C操作来操作它。
In addition please read this answer: Mixing C functions in an Objective-C class
另外请阅读以下答案:在Objective-C类中混合C函数
#2
25
To call Objective-C code from a C callback I would use something like:
要从C回调调用Objective-C代码,我会使用类似的东西:
void * refToSelf;
int cCallback()
{
[refToSelf someMethod:someArg];
}
@implementation SomeClass
- (id) init
{
self = [super init];
refToSelf = self;
}
- (void) someMethod:(int) someArg
{
}
#3
8
Can/How do I call an Objective-C method in place of this?
可以/如何使用Objective-C方法代替此方法?
You cannot.
你不能。
Can/Should I mix C function in with my Objective-C call?
可以/我应该将C函数与Objective-C调用混合使用吗?
Yes. Write a C function and use that as the callback to the CF function.
是。编写C函数并将其用作CF函数的回调函数。
How do I mix C function with Objective-C methods?
如何将C函数与Objective-C方法混合使用?
You can set self
as the info
pointer in your context structure. That will be passed to the callback. Then, in the callback, cast the info
pointer back to id
:
您可以将self设置为上下文结构中的信息指针。那将被传递给回调。然后,在回调中,将信息指针强制转换为id:
MyClass *self = (id)info;
You can then send self
messages. You still can't directly access instance variables, though, since a C function is outside of the @implementation
section. You'll have to make them properties. You can do this with a class extension. (Contrary to what that document says, you would not declare the extension inside @implementation
, but in the same file with it, generally right above it.)
然后,您可以发送自我消息。但是,您仍然无法直接访问实例变量,因为C函数位于@implementation部分之外。你必须把它们作为属性。您可以使用类扩展来执行此操作。 (与该文档所说的相反,你不会在@implementation中声明扩展名,而是在与它相同的文件中,通常在它上面。)
#4
5
What I've always found helpful in this situation is to make an Obj-C wrapper on top of the C API. Implement what you need to using C functions, and build an Objective-C class (or two) on top of it, so that's all the outside world will see. For example, in the case of a callback like this, you might make a C function that calls Obj-C delegate methods on other objects.
我总是发现在这种情况下有用的是在C API之上创建一个Obj-C包装器。实现使用C函数所需的内容,并在其上构建一个Objective-C类(或两个),以便外部世界都能看到。例如,在这样的回调的情况下,您可以创建一个C函数,在其他对象上调用Obj-C委托方法。
#1
48
Mixing C and Objective-C methods and function is possible, here is a simple example that uses the SQLite API within an iPhone App: (course site)
可以混合使用C和Objective-C方法和函数,这是一个在iPhone App中使用SQLite API的简单示例:(课程网站)
Download the Zip file (09_MySQLiteTableView.zip)
下载Zip文件(09_MySQLiteTableView.zip)
C functions need to be declared outside of the @implementation
in an Objective-C (.m) file.
需要在Objective-C(.m)文件中的@implementation之外声明C函数。
int MyCFunction(int num, void *data)
{
//code here...
}
@implementation
- (void)MyObjectiveCMethod:(int)number withData:(NSData *)data
{
//code here
}
@end
Because the C function is outside of the @implementation
it cannot call methods like
因为C函数在@implementation之外,所以它不能调用像
[self doSomething]
and has no access to ivars.
并且无法访问ivars。
This can be worked around as long as the call-back function takes a userInfo
or context
type parameter, normally of type void*
. This can be used to send any Objective-C object to the C function.
只要回调函数采用userInfo或context类型参数(通常为void *类型),就可以解决此问题。这可用于将任何Objective-C对象发送到C函数。
As in the sample code, this can be manipulated with normal Objective-C operations.
与示例代码中一样,可以使用正常的Objective-C操作来操作它。
In addition please read this answer: Mixing C functions in an Objective-C class
另外请阅读以下答案:在Objective-C类中混合C函数
#2
25
To call Objective-C code from a C callback I would use something like:
要从C回调调用Objective-C代码,我会使用类似的东西:
void * refToSelf;
int cCallback()
{
[refToSelf someMethod:someArg];
}
@implementation SomeClass
- (id) init
{
self = [super init];
refToSelf = self;
}
- (void) someMethod:(int) someArg
{
}
#3
8
Can/How do I call an Objective-C method in place of this?
可以/如何使用Objective-C方法代替此方法?
You cannot.
你不能。
Can/Should I mix C function in with my Objective-C call?
可以/我应该将C函数与Objective-C调用混合使用吗?
Yes. Write a C function and use that as the callback to the CF function.
是。编写C函数并将其用作CF函数的回调函数。
How do I mix C function with Objective-C methods?
如何将C函数与Objective-C方法混合使用?
You can set self
as the info
pointer in your context structure. That will be passed to the callback. Then, in the callback, cast the info
pointer back to id
:
您可以将self设置为上下文结构中的信息指针。那将被传递给回调。然后,在回调中,将信息指针强制转换为id:
MyClass *self = (id)info;
You can then send self
messages. You still can't directly access instance variables, though, since a C function is outside of the @implementation
section. You'll have to make them properties. You can do this with a class extension. (Contrary to what that document says, you would not declare the extension inside @implementation
, but in the same file with it, generally right above it.)
然后,您可以发送自我消息。但是,您仍然无法直接访问实例变量,因为C函数位于@implementation部分之外。你必须把它们作为属性。您可以使用类扩展来执行此操作。 (与该文档所说的相反,你不会在@implementation中声明扩展名,而是在与它相同的文件中,通常在它上面。)
#4
5
What I've always found helpful in this situation is to make an Obj-C wrapper on top of the C API. Implement what you need to using C functions, and build an Objective-C class (or two) on top of it, so that's all the outside world will see. For example, in the case of a callback like this, you might make a C function that calls Obj-C delegate methods on other objects.
我总是发现在这种情况下有用的是在C API之上创建一个Obj-C包装器。实现使用C函数所需的内容,并在其上构建一个Objective-C类(或两个),以便外部世界都能看到。例如,在这样的回调的情况下,您可以创建一个C函数,在其他对象上调用Obj-C委托方法。