开发者

iPhoneOS: using detachNewThreadSelector method inside a C++ class method

I have a C++ class method where i need to call the "detachNewThreadSelector" method with all the parameters.

Here lies the problem, as my class is not objective C i don't have a self pointer. Also i don't see how i will be able to call a class method from the method that i will set as selector.

Please do ask if my question is not clear, i am not from a english speaking country.

Here is some code.

ALuint AudioController::PlayStream(const string& asset)  
{  
        //attach to a thread  
    [NSThread detachNewThreadSelector:(SEL)selector     toTarget:(id)selfwithObject:(id)argument]

}

void AudioController::RotateThread(const string& soundKey)  
{  
}

As you can see how do i pass the RotateThread method as a selector to th开发者_高级运维e "detachNewThreadSelector" and also where do i get the self pointer.

Any help much appreciated.

Thanks


You can't do this. It isn't as a simple as "Where do I get the self pointer?" The actual question is, "Where do I get something that can respond to messages?" Because a C++ class can't.

Objective-C classes, objects and methods are completely different things from C++ classes, objects and methods. The fact that the two languages use the same terminology and use the things for similar purposes confuses a lot of people, but to be clear: They are totally different things that work in very different ways in the two languages. Case in point: C++ methods are simply called rather than dispatched based on a selector like Objective-C methods. And C++ classes aren't even objects.

You have two real options here:

  1. Create an Objective-C class that has the behavior you want.

  2. Use a C++ concurrency solution.


you may not use c++ object in this manner (as an argument to this NSThread method). if your case is simple (read: few interfaces declared), then you can create a utility (objc) class to handle the message, and to then pass the argument back to the AudioController instance. illustration:

(non-compiled pseudo code follows)

namespace pseudo_object {
template <typename> class reference_counted;
}

@interface MONAudioControllerWorker : NSObject
{
    pseudo_object::reference_counted<AudioController> audioController_;
    std::string asset_;
}

+ (MONAudioControllerWorker *)newMONAudioControllerWorkerWithAudioController:(pseudo_object::reference_counted<AudioController>&)audioController asset:(const std::string&)asset;
- (void)secondaryWorker;

@end

@implementation MONAudioControllerWorker

+ (MONAudioControllerWorker *)newMONAudioControllerWorkerWithAudioController:(pseudo_object::reference_counted<AudioController>&)audioController asset:(const std::string&)asset
{
/* ... */
}

- (void)secondaryWorker
{
    NSAutoreleasePool * pool([NSAutoreleasePool new]);
    audioController_->RotateThread(asset_);
    [pool release];
}

@end
/* static */
ALuint AudioController::PlayStream(pseudo_object::reference_counted<AudioController>& This, const string& asset)
{
/* attach to a thread */
    MONAudioControllerWorker * controller = [MONAudioControllerWorker newMONAudioControllerWorkerWithAudioController:This asset:asset];
    [NSThread detachNewThreadSelector:@selector(secondaryWorker) toTarget:controller withObject:0];
    [controller release];
}

sometimes it is just easier to create an objc class which may contain a simplified (generic) interface for this purpose (i.e. reusable beyond this object), or to use more traditional threading routines (pthreads). if this is the only case in the project, then it should be fine. otherwise, you end up with many utility classes/symbols and much more to maintain. illustration:

@interface MONAudioControllerWrapper : NSObject
{
    AudioController audioController_;
    std::string asset_;
}

+ (MONAudioControllerWrapper *)newMONAudioControllerWrapperWithAsset:(const std::string&)asset;

- (void)playStream;

@end

@implementation MONAudioControllerWrapper

+ (MONAudioControllerWrapper *)newMONAudioControllerWrapperWithAsset:(const std::string&)asset
{
/* ... */
}

- (void)secondaryWorker
{
    NSAutoreleasePool * pool([NSAutoreleasePool new]);
    audioController_->RotateThread(asset_);
    [pool release];
}

- (void)playStream
{
    [NSThread detachNewThreadSelector:@selector(secondaryWorker) toTarget:self withObject:0];
}

@end


As others have said, you can't use detachThreadWithSelector: passing a C++ object as a target or using a C++ method as the selector.

You have two strategies:

  1. wrap the object and selector with an OBjective-C object and selector e.g.

    myAudioControllerWrapper = [[OCAudioControllerWrapper alloc] initWithRealController: this];
    // need some code to release once thread is complete
    [NSThread detachNewThreadSelector: @selector(wrapperSelector:) target: myAudioControllerWrapper withObject: soundKeyAsNSObject];
    

    and your wrapper selector looks like:

    -(void) wrapperSelector: (id) key
    {
        cppController->rotateThread([key cppObject]);
    }
    
  2. Use some other thread mechanism more in keeping with the C++ paradigm. Grand Central Dispatch might be the one if your platform supports it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜