2011-01-21 77 views
2

我正在为iPhone编写游戏。几乎所有的代码都是用C++编写的。现在我想使用NSThread创建一个新线程(我想使用runLoop)。iPhone:从C++对象开始NSThread

如果代码是用.mm文件编写的,那么可以混合使用Objective-C和C++。

的问题是,用于创建NSThread

NSThread* myThread = [[NSThread alloc] initWithTarget:self selector:@selector(workerThreadFunction:) object:nil]; 
[myThread start]; 

我需要通过“自我”其中(据我所知)一个Objective-C“ID” - 和C++对象是不一个客观的c对象。

所以 - 有没有一种方法可以在C++应用程序中使用NSThread,还是我不得不使用pthread?

谢谢!

+0

你并不需要传递的自我,你可以通过任何Objective-C的对象。 – 2011-01-21 20:13:01

+0

所以它意味着我不能将threadMain函数定义为我的C++对象的成员函数? – Mat 2011-01-21 20:15:10

+0

不,但是你可以制作一个虚拟的objective-c对象,用你的C++对象进行初始化,然后调用你回来 – 2011-01-21 20:19:47

回答

0

您不能从Objective C类派生C++类,反之亦然。设计一个包装器ObjC对象,它将实例化并调用(但不能从C++继承)。这通常被称为“遏制和委托”。

或者您可以使用POSIX线程而不是NSThread。

2

可不知何故,我创建一个Objective-C对象, - 在它的构造 - 采用C++函数指针,它后来调用的参数?

当然。就像这样:

//The C++ base 
class ThreadBase 
{ 
    virtual void Run() = 0; 
}; 

typedef ThreadBase * (*ThreadCreator)(); 

//The ObjC wrapper 

@interface ThreadStarter:NSObject 
{ 
    ThreadCreator TheCreator; 
} 

-(void)Run; 
-(id)init:(ThreadCreator)tc; 
@end 

@implementation ThreadStarter 
-(id)init:(ThreadCreator)tc 
{ 
    TheCreator = tc; 
    return [super init]; 
} 

-(void)Run 
{ 
    (*TheCreator)()->Run(); 
} 
@end 

// 
class MyThread: public ThreadBase 
{ 
//... 
}; 

ThreadBase *MyThreadCreator() 
{ 
    return new MyThread(); 
} 

//And finally usage 

ThreadStarter *tc = [[ThreadStarter alloc]init:MyThreadCreator]; 
NSThread* myThread = [[NSThread alloc] initWithTarget:tc selector:@selector(Run) object:nil]; [myThread start]; 

它是由创作者的功能,因为你想要它了参数化。但是你也可以按类进行参数化。

0

对于C++ - 我以前的答案的风格的改写:

//The C++ base 
class ThreadBase 
{ 
    virtual void Run() = 0; 
}; 

//The ObjC wrapper 

@interface ThreadStarter:NSObject 
{ 
    ThreadBase *TheThread; 
} 

-(void)Run; 
-(id)init:(ThreadBase)tb; 
@end 

@implementation ThreadStarter 
-(id)init:(ThreadBase)tb 
{ 
    TheThread = tb; 
    return [super init]; 
} 

-(void)Run 
{ 
    TheThread->Run(); 
} 
@end 

// 
class MyThread: public ThreadBase 
{ 
    //...   
}; 

//And finally usage 

MyThread *Thread = new MyThread(); 
ThreadStarter *tc = [[ThreadStarter alloc]init:Thread]; 
NSThread* myThread = [[NSThread alloc] initWithTarget:tc selector:@selector(Run) object:nil]; 
[myThread start]; 

干净多了这种方式,恕我直言。如果你坚持认为线程启动例程处于atrbitrary类不是你创造的任意函数,这里是你的答案:

class MyThread: public ThreadBase, public MyOtherObject 
{ 
    void Run() 
    { 
     DoWork(); //Function defined in MyOtherObject 
    } 
} 

你看,如果你想通过成员函数,参数化,你必须参数化由功能和类。在C++中,类不能成为运行时变量。

1

“我可以以某种方式创建一个客观的C对象,在它的构造函数中,它将一个C++函数指针作为它后来调用的参数?”

是的,但它相当丑陋。

首先,定义一个回调基类和一个模板版本。这可以进入一个通用的.h文件,该文件可以是来自.cpp和.mm文件的#includ。还定义了基本CThread类:

// Thread.h 
#pragma once 
#include <objc/objc.h> // for a cpp compatible definition of id 
class Callback{ 
public: 
    virtual void operator()(void)=0; 
}; 

template<class T> 
class ClassCallback : public Callback { 
    T* _classPtr; 
    typedef void(T::*fncb)(void); 
    fncb _cbProc; 
public: 
    ClassCallback(T* classPtr,fncb cbProc):_classPtr(classPtr),_cbProc(cbProc){} 
    virtual void operator()(void){ 
    (_classPtr->*_cbProc)(); 
    } 
}; 

class CThread { 
    id _thread; 
public: 
    void Start(Callback* cb); 
}; 

接下来,把实施CThread,它的对象 - 哥们对象,在。毫米文件:

// Thread.mm 
#import <Cocoa/Cocoa.h> 
#import "Thread.h" 

@interface ThreadStarter:NSObject 
{ 
    Callback *theCallback; 
} 

-(void)Run; 
-(id)init:(Callback*)cb; 
@end 

@implementation ThreadStarter 
-(id)init:(Callback*)cb 
{ 
    theCallback = cb; 
    return [super init]; 
} 

-(void)Run 
{ 
    theCallback(); 
} 
@end 

void CThread::Start(Callback* cb){ 
    _thread = [[ThreadStarter alloc] init:cb]; 
    [NSThread detachNewThreadSelector:@selector(Run) 
         toTarget:_thread 
        withObject:nil]; 
    } 
}; 

,然后在你的应用程序的CPP文件,您可以:

// MyClass.cpp (doesn't even have to be .mm) 
#include "Thread.h" 

class MyClass { 
    CThread _myThread; 
    void SomeArbMethod(){ 
    } 
public: 
    MyClass(){ 
    _myThread.Start(new ClassCallback<MyClass>(this,&MyClass::SomeArbMethod)); 
    } 
};