我正在为RS232端口编写小类。它可以同步写入和异步读取。因此,对于异步读取,我使用第二个线程,即等待输入数据。收到数据时,我想用输入数据调用用户回调(我得到的构造函数参数)。它看起来像:
typedef int (*ReceivedCallback)(string data);
class RS232
{
RS232(string portName, ReceivedCallback dataReceived);
~RS232();
private:
ReceivedCallback dataReceivedCallback;
private:
static unsigned ReaderThread(void* data);
public:
SendData(string data);
}
我的问题是:ReaderThread必须是静态的,以将指针传递给_beginthreadex()函数。在ReaderThread中我想调用“dataReceivedCallback”,从构造函数中的用户获取。但我不能,因为我无法在静态ReaderThread中调用非静态函数。另外,我不能使“dataReceivedCallback”静态,因为我可能有很多我的类实例(对于COM1,COM2,COM3),并且每个实例都应该有自己的回调,由用户获取。
我的架构错误在哪里?你会如何实现它?
提前致谢!
P.S。使用Visual Studio 2005。
答案 0 :(得分:2)
您需要将指向RS232
的实例的指针传递给ReaderThread
,然后将该指针传递给static
回调,或直接调用非{{ {1}}对象上的{1}}方法。
我还会使用static
而不是RS232
。我的代码示例将使用[CreateThread][1]
,但如果您愿意,可以将该技术调整为beginthreadex
。
简单地说,当开始CreateThread
时,将指针传递给实例:
beginthreadex
...使用ReaderThread
将其投回:
RS232* myObj = new RS232;
CreateThread (..., myObj);
更改回调函数,以便它也可以传递实例:
reinterpret_cast
现在在回调中你可以调用成员函数:
unsigned RS232::ReaderThread (void* data)
{
RS232* that = reinterpret_cast <RS232*> (data);
}
答案 1 :(得分:1)
您需要将额外的参数传递给线程函数(您已经有void *data
可用)。
现在,将其添加为class RS232
中的私有元素:
class RS232
{
RS232(string portName, ReceivedCallback dataReceived);
~RS232();
private:
ReceivedCallback dataReceivedCallback;
private:
static unsigned ReaderThread(void* data);
public:
SendData(string data);
}
并在构造函数中:
RS232::RS232(string portName, ReceivedCallback dataReceived)
{
... various stuff to initialize the serial port ...
_beginthreadex(securityarg, stacksize, ReaderThread, this, ...)
}
在ReaderThread函数中:
unsigned RS232::ReaderThread(void *data)
{
RS232 *self = static_cast<RS232*>(data);
.... stuff to read from serial port ...
... Now call the callback:
self->dataReceivedCallback(str);
....
}
答案 2 :(得分:1)
要访问静态线程函数中的非静态对象数据,您可以使用这个非常hacky和未经测试的解决方案。但要注意 - 它仅用于教育目的,因为它非常黑客。您应该了解锁和互斥锁,并可能提升线程。注意,这是一种pthread风格的解决方案。我没有使用函数_beginthreadex()的经验,但你可以看到createThread完成了创建线程的工作。根据需要进行调整。
typedef int (*ReceivedCallback)(string data);
class RS232
{
public:
RS232(string portName, ReceivedCallback dataReceived);
~RS232();
SendData(string data);
createThread();
private:
ReceivedCallback dataReceivedCallback;
static unsigned ReaderThread(void* data);
thread m_someThread;
struct accessHelper
{
RS232* This;
void *actual_arg;
accessHelper(RS232 *t, void *p)
: This(t),
actual_arg(p)
{}
};
};
RS232::createThreaad()
{
int someData;
accessHelper ah(this, someData);
m_someThread.create(RS232::ReaderThread, &ah);
}
RS232::ReaderThread(void *data)
{
accessHelper *ah = static_cast<accessHelper*>(data);
RS232 *This = ah->This;
This->dataReceivedCallback......
}