RT-Thread线程创建接口使用的是C函数,对于C++类成员变量因含有隐式传参this
,所以并不能直接把C++的类成员函数作为线程入口函数。
目前主流方式有两种:定义类静态成员函数
、使用模板函数
。
一、定义类静态成员函数
只需要在普通成员函数前加上static
就变成了静态成员函数,静态成员函数没有隐式传参无需实例化也可以调用。但是静态成员函数只能访问类静态成员变量,使用不便,不推荐此法。
二、使用模板函数
使用模板函数来进行类成员函数的前置转换,将隐式传参转换成显示传参。使用方便,无限制。此方法也可适用于其它类似接口。
具体使用方法如下:
//main.cxx
#include <rtthread.h>
#include <string.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
//TYPE:类名
//void (TYPE::*run)():线程入口函数
//使用时类中线程入口必须和模板函数定义入口相同,此处为[run]
//你可以修改为指定的名称,建议以模板函数线程为标准来修改类成员函数线程入口名
template<typename TYPE,void (TYPE::*run)()>
void _thread_t(void *parameter)
{
TYPE* t = (TYPE*)parameter;
t->run();
}
class Test {
public:
Test(){}
virtual ~Test(){}
//函数名保持和_thread_t函数模板线程入口名相同
void run() {
rt_kprintf("%s id:0x%x\n",__FUNCTION__ ,rt_thread_self());
}
};
void thread_test()
{
Test t;
rt_kprintf("%s thread id:0x%x\n",__FUNCTION__ ,rt_thread_self());
//entry:传递模板函数_thread_t
rt_thread_t th = rt_thread_create("Test_th", _thread_t<Test,&Test::run>, &t, 512, 20, 5);
if (RT_NULL == th) {
rt_kprintf("thread create failed.\n");
return;
}
rt_kprintf("start Test::run thread:0x%x\n",th);
rt_thread_startup(th);
}
int main()
{
return RT_EOK;
}
MSH_CMD_EXPORT(thread_test,thread test);
RT-Thread编译C++代码时请打开C++
和libc
功能,并且需要将你的C++代码的文件名后缀更改为.cpp
或.cxx
或其它表C++文件的后缀名。
编译运行在finsh终端
输入help
命令发现已经多了一条thread_test
命令,键入此命令输出如下结果:
msh >thread_test
thread_test thread id:0x20001b10
start Test::run thread:0x2000105c
msh >run id:0x2000105c
可以发现run函数可以被正常调用且启动的线程ID和run函数里面运行的线程ID相同。