我想使用C函数启动一个新线程,而不是使用Objective-C方法。我试过了
[NSThread detachNewThreadSelector: @selector(func) toTarget: nil withObject: id(data)];
我在哪里
void func(void *data) {
// ...
}
和data
是void *
,但我在objc_msgSend
中遇到了运行时崩溃,从
-[NSThread initWithTarget:selector:object:]
我该怎么做?它甚至可能吗?
答案 0 :(得分:10)
滚动你自己:
// In some .h file. #import to make the extension methods 'visible' to your code.
@interface NSThread (FunctionExtension)
+(void)detachNewThreadByCallingFunction:(void (*)(void *))function data:(void *)data;
-(id)initWithFunction:(void (*)(void *))function data:(void *)data;
@end
// In some .m file.
@implementation NSThread (FunctionExtension)
+(void)startBackgroundThreadUsingFunction:(id)object
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
void (*startThreadFunction)(void *) = (void (*)(void *))[[object objectForKey:@"function"] pointerValue];
void *startThreadData = (void *) [[object objectForKey:@"data"] pointerValue];
if(startThreadFunction != NULL) { startThreadFunction(startThreadData); }
[pool release];
pool = NULL;
}
+(void)detachNewThreadByCallingFunction:(void (*)(void *))function data:(void *)data
{
[[[[NSThread alloc] initWithFunction:function data:data] autorelease] start];
}
-(id)initWithFunction:(void (*)(void *))function data:(void *)data
{
return([self initWithTarget:[NSThread class] selector:@selector(startBackgroundThreadUsingFunction:) object:[NSDictionary dictionaryWithObjectsAndKeys:[NSValue valueWithPointer:function], @"function", [NSValue valueWithPointer:data], @"data", NULL]]);
}
@end
注意:我在上面编写了代码,并将其放在公共域中。 (有时律师喜欢这种东西)它也 完全未经测试!
如果你能保证线程入口函数也能创建一个......你可以随时删除NSAutoreleasePool
位......但是它没有任何损失,没有速度惩罚,并且调用任意C函数更简单。我会说保持它。
你可以像这样使用它:
void bgThreadFunction(void *data)
{
NSLog(@"bgThreadFunction STARTING!! Data: %p", data);
}
-(void)someMethod
{
// init and then start later...
NSThread *bgThread = [[[NSThread alloc] initWithFunction:bgThreadFunction data:(void *)0xdeadbeef] autorelease];
// ... assume other code/stuff here.
[bgThread start];
// Or, use the all in one convenience method.
[NSThread detachNewThreadByCallingFunction:bgThreadFunction data:(void *)0xcafebabe];
}
运行时:
2009-08-30 22:21:12.529 test[64146:1303] bgThreadFunction STARTING!! Data: 0xdeadbeef
2009-08-30 22:21:12.529 test[64146:2903] bgThreadFunction STARTING!! Data: 0xcafebabe
答案 1 :(得分:3)
使用简单调用该函数的方法创建一个Objective-C类。选择该方法的选择器并将其传递给NSThread
API。
答案 2 :(得分:3)
好吧,我不确定是否可能,但请记住,每个Objective-C方法都有两个隐式/隐藏参数self
和_cmd
。 IMP
typedef
通常是这样的:
typedef id (*IMP)(id,SEL,...);
如果你想要方法和选择器,你需要有一个看起来像这样的方法:
void func (id self, SEL _cmd, void *firstParameter);
但即使在那之后,你需要在运行时注册选择器名称,然后你需要将该选择器与方法相关联,但这是在逐类的基础上完成的(即类可以有不同的实现相同的选择器名称),所以你至少需要一个虚拟类。
创建该类的虚拟类和虚拟实例比调用各种运行时API只是为了让NSThread
调用单个C函数要简单得多。
答案 3 :(得分:1)
如果您不需要NSThread
内容,也可以使用direct POSIX interface启动帖子。
答案 4 :(得分:0)