【问题标题】:No matching function for call to pthread_create Objective-C ARC conversion没有匹配函数调用 pthread_create Objective-C ARC 转换
【发布时间】:2018-07-22 20:16:00
【问题描述】:

正在将我的项目转换为 ARC,但由于以下错误“没有用于调用 pthread_create 的匹配函数”而无法转换。这是它所在的代码,专门发生在以pthread create 开头的行上。我怎样才能解决这个问题?它还在错误下方的侧栏中显示Candidate function not viable: no known conversion from 'NSString *' to 'void * _Nullable' for 4th argument

我已经切断了其余的功能,但如果需要可以提供更多细节。

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));
    }
}

【问题讨论】:

    标签: objective-c memory-management automatic-ref-counting


    【解决方案1】:

    由于您的错误消息表明pthread_create 的第四个参数是void * 类型。在 ARC 下,您不能简单地将 Obj-C 对象引用作为 void * 传递,因为一旦将引用存储在 C(++) 指针变量中,ARC 将无法跟踪该引用,因此无法管理对象的内存。

    对于必须将 Obj-C 引用传递到 C(++) 世界的情况,可以使用 bridge cast 来告知 ARC 应该如何管理内存。但是,在您的情况下,有更好的方法,只需传递 C++ 指针 name,而不创建 NSString。如果loadWorldThread 期望std::string 无论如何都是正确的做法。如果它需要NSString *,那么:

    • 修改它以采用std::string 并在其中进行任何所需的转换为NSString *;或

    • 编写一个小的中间函数,它接受std::string,从中生成NSString *,然后调用loadWorldThread。将这个新函数传递给pthread_create

    执行上述任一操作可避免在pthread_create 调用中使用桥接将Obj-C 引用移入C(++) 世界并脱离ARC 控制;和loadWorldThread(或上述中间函数)中的另一个桥,将其移回 Obj-C 世界并进入 ARC 控制。

    附录

    扩展最后一段,因为那里的方法似乎更适合您的情况。首先,假设您的代码:

    nsstring(name)
    

    获取std::string 类型的值并返回NSString 类型的值,如果没有,则查找如何进行此转换。

    在上述表达式之后,您有一个在 ARC 控制下的 NSString 引用。您不能简单地传递 void * 这样的引用,您必须首先将其从 ARC 的控制中移除并对其内存管理负责(但不会持续多久)。您可以将您的NSString * 桥接到CFStringRef

    CFStringRef cfName = (__bridge_retain CFStringRef)nsstring(name);
    

    您现在可以将cfName(对堆分配的CFString 的引用)作为void * 传递。

    现在在loadWorldThread;应该声明采用void *,类似于void loadWorldThread(void *arg) { ... };您需要将您的 CFStringRef 桥接回 NSString * 并将其内存管理的责任交还给 ARC:

    NSString *nsName = (__bridge_transfer NSString *)arg;
    

    以上是通过匿名引用 (void *) 传递 ARC 控制引用的标准模式。

    (注意:上面使用CFStringRef 来表明您正在传递对手动管理的CFString 的引用,您可以直接转换为void * 并再次返回,确实您会注意到回退 arg 时并没有首先转换为 CFStringRef 来证明这一点。)

    HTH

    【讨论】:

    • 我该怎么做呢?很抱歉询问勺子喂食,但我已经尝试过查找但无法解决
    • 你不明白什么?假设您可以修改loadWorldThread 而不是调用nsstring(name) 并将其结果传递给pthread_create,而只需传递name 并在loadWorldThread 内部执行nsstring(name)
    • stackoverflow.com/questions/48911474/… 我已经尝试过我认为可以解决的问题,但就我所知,知道该怎么做吗?
    • 首先,最好编辑这个问题而不是问一个新问题,尤其是当您尝试遵循上面的答案时。在您的新代码中,您传递的是&name,这不是std::string,而是堆栈上变量的地址。如果您不能传递 std::string 本身,因为它是堆栈分配的(所以不仅仅是一个可以作为 void * 传递的堆指针),您需要将其转换为堆分配的字符串在调用pthread_create 之前 - 从中​​创建一个CFString,因为它可以作为void * 传递,然后在loadWorldThread [继续...]
    • [...cont] 桥将其转移到NSString,因此 ARC 负责其内存管理。您可能需要阅读桥牌转换,必须了解这里的内存管理语义,否则您很容易遇到麻烦。
    猜你喜欢
    • 1970-01-01
    • 2011-11-01
    • 2015-06-13
    • 2020-10-07
    • 1970-01-01
    • 2019-11-08
    • 1970-01-01
    • 2021-09-21
    相关资源
    最近更新 更多