C - 将 void* 转换为 thrd_create() 中的结构
C - cast void* to structure in thrd_create()
我知道有很多关于将 void* 转换为 struct 的问题得到了解答,但我无法使其以正确的方式工作。
好吧,我想创建一个线程来在后台播放音乐。我有一个结构,它收集加载的音乐文件数组以及开始和结束索引:
typedef unsigned char SoundID;
typedef unsigned char SongID;
typedef struct {
Mix_Music *songs[9]; // array of songs
SongID startId; // index of first song to play
SongID endId; // index of last song to play
} SongThreadItem;
然后我想通过创建线程并将实际播放歌曲的函数传递给 thread_create()
函数来播放歌曲。
int play_songs(Mix_Music *songs[9], SongID startId, SongID endId, char loop){
thrd_t thrd;
SongThreadItem _item;
SongThreadItem *item = &_item;
memcpy(item->songs, songs, sizeof(item->songs));
item->startId = startId;
item->endId = endId;
printf("item->startId is %i\n", item->startId);
printf("item->endId is %i\n", item->endId);
thrd_create_EC(thrd_create(&thrd, audio_thread_run, item));
return 0;
}
int audio_thread_run(void *arg){
SongThreadItem *item = arg; // also tried with = (SongThreadItem *)arg
printf("item->startId is %i\n", item->startId);
printf("item->endId is %i\n", item->endId);
free(item);
return 0;
}
然后我得到以下输出:
item->startId is 0
item->endId is 8
item->startId is 6
item->endId is 163
在 audio_thread_run()
中检索到的值不是预期的值。我不知道我是否放了足够多的代码让别人发现我的错误,我尽量减少它,因为它是一个更大项目的一部分。
在此先感谢您的帮助。
SongThreadItem _item;
SongThreadItem *item = &_item; // bug
这是一个问题:您为线程提供了一个指向堆栈变量的指针。堆栈将被主线程中发生的几乎所有事情覆盖。您需要在此处分配动态内存(使用 malloc
),并在不再需要时注意释放它(可能在线程例程本身中)。
其他选项将是一个全局结构,用于跟踪所有活动线程及其起始数据,或类似的东西。但它会涉及动态分配,除非线程数在编译时是固定的。
该线程异步运行,但您向它传递了一个指向 SongThreadItem 的指针,该指针位于调用 play_songs()
.
的线程的堆栈上
如果您只有一个线程调用 play_songs()
,并且在您完成 item
之前不会再次调用它,您可以这样定义 _item
:
static SongThreadItem _item;
这样就在数据段,不会被覆盖
如果您不知道何时以及谁会调用 play_songs()
,那么在您完成后只需 malloc
_item
和 free
它在线程中:
...
SongThreadItem *item = (SongThreadItem *)malloc(sizeof(SongThreadItem));
...
后者通常是更好的主意。将其视为将数据的所有权传递给新线程。当然,如果线程创建失败,生产质量代码应该释放该项目。
我知道有很多关于将 void* 转换为 struct 的问题得到了解答,但我无法使其以正确的方式工作。
好吧,我想创建一个线程来在后台播放音乐。我有一个结构,它收集加载的音乐文件数组以及开始和结束索引:
typedef unsigned char SoundID;
typedef unsigned char SongID;
typedef struct {
Mix_Music *songs[9]; // array of songs
SongID startId; // index of first song to play
SongID endId; // index of last song to play
} SongThreadItem;
然后我想通过创建线程并将实际播放歌曲的函数传递给 thread_create()
函数来播放歌曲。
int play_songs(Mix_Music *songs[9], SongID startId, SongID endId, char loop){
thrd_t thrd;
SongThreadItem _item;
SongThreadItem *item = &_item;
memcpy(item->songs, songs, sizeof(item->songs));
item->startId = startId;
item->endId = endId;
printf("item->startId is %i\n", item->startId);
printf("item->endId is %i\n", item->endId);
thrd_create_EC(thrd_create(&thrd, audio_thread_run, item));
return 0;
}
int audio_thread_run(void *arg){
SongThreadItem *item = arg; // also tried with = (SongThreadItem *)arg
printf("item->startId is %i\n", item->startId);
printf("item->endId is %i\n", item->endId);
free(item);
return 0;
}
然后我得到以下输出:
item->startId is 0
item->endId is 8
item->startId is 6
item->endId is 163
在 audio_thread_run()
中检索到的值不是预期的值。我不知道我是否放了足够多的代码让别人发现我的错误,我尽量减少它,因为它是一个更大项目的一部分。
在此先感谢您的帮助。
SongThreadItem _item;
SongThreadItem *item = &_item; // bug
这是一个问题:您为线程提供了一个指向堆栈变量的指针。堆栈将被主线程中发生的几乎所有事情覆盖。您需要在此处分配动态内存(使用 malloc
),并在不再需要时注意释放它(可能在线程例程本身中)。
其他选项将是一个全局结构,用于跟踪所有活动线程及其起始数据,或类似的东西。但它会涉及动态分配,除非线程数在编译时是固定的。
该线程异步运行,但您向它传递了一个指向 SongThreadItem 的指针,该指针位于调用 play_songs()
.
如果您只有一个线程调用 play_songs()
,并且在您完成 item
之前不会再次调用它,您可以这样定义 _item
:
static SongThreadItem _item;
这样就在数据段,不会被覆盖
如果您不知道何时以及谁会调用 play_songs()
,那么在您完成后只需 malloc
_item
和 free
它在线程中:
...
SongThreadItem *item = (SongThreadItem *)malloc(sizeof(SongThreadItem));
...
后者通常是更好的主意。将其视为将数据的所有权传递给新线程。当然,如果线程创建失败,生产质量代码应该释放该项目。