converting my project to ARC but says it can't due to the following error 'No matching function for call to pthread_create'. Here is the code it falls in, happens specifically on the line starting with pthread create
. How can I fix this? It also says Candidate function not viable: no known conversion from 'NSString *' to 'void * _Nullable' for 4th argument
in the sidebar underneath the error.
I've cut off the rest of the function but can provide more detail if necessary.
void World::loadWorld(std::string name)
{
if(doneLoading==0)
{
doneLoading=1;
Resources::getResources->stopMenuTune();
if(LOW_MEM_DEVICE)
{
menu->deactivate();
Resources::getResources->unloadMenuTextures();
terrain->allocateMemory();
terrain->loadTerrain(name,TRUE);
doneLoading=2;
hud->fade_out=1;
}
else
{
terrain->allocateMemory();
pthread_t foo;
pthread_create(&foo,NULL,loadWorldThread, nsstring(name));
}
}
As your error message indicates the 4th argument to
pthread_create
is of typevoid *
. Under ARC you cannot simply pass an Obj-C object reference as avoid *
as ARC would is not able to track the reference once it is stored in a C(++) pointer variable, and therefore cannot manage the object's memory.For situations where an Obj-C reference must be passed into the C(++) world a bridge cast can be used to inform ARC how the memory should be managed. However in your case there a better way, just pass the C++ pointer,
name
, without creating anNSString
. IfloadWorldThread
expects astd::string
that is the correct thing to do anyway. If it expects anNSString *
then either:modify it to take a
std::string
and do any required conversion toNSString *
within it; orwrite a small intermediate function which takes a
std::string
, produces anNSString *
from it, and then callsloadWorldThread
. Pass this new function topthread_create
.Doing either of the above avoids the use of a bridge cast in the
pthread_create
call to move the Obj-C reference into the C(++) world and out of ARC control; and another bridge cast inloadWorldThread
(or intermediate function as above) to move it back into the Obj-C world and into ARC control.Addendum
Expanding on the last paragraph, as the method there seems better suited to your situation. First, it is assumed that your code:
takes a value of type
std::string
and returns a value of typeNSString
, if it does not then look up how to do this conversion.After the above expression you have a reference to an
NSString
under ARC control. You cannot simply pass such a reference as avoid *
, you must take it out of ARC's control first and take responsibility for its memory management (but not for long as you will see). You can bridge cast yourNSString *
to aCFStringRef
:You can now pass
cfName
, which is a reference to a heap-allocatedCFString
, as avoid *
.Now in
loadWorldThread
; which should be declared to take avoid *
, something likevoid loadWorldThread(void *arg) { ... }
; you need to bridge cast yourCFStringRef
back toNSString *
and hands responsibility for its memory management back to ARC:The above is a standard pattern to pass an ARC controlled reference though an anonymous reference (
void *
).(Note: the above uses
CFStringRef
to make it clear that you are passing around a reference to a manually managedCFString
, you can cast directly tovoid *
and back again, indeed you will notice that when casting backarg
was not first cast to aCFStringRef
to demonstrate this.)HTH