如何在C ++ Builder2009中正确地将指针从void *转发到TMemo *?

时间:2008-11-08 15:45:13

标签: c++ c++builder downcast tmemo

我在C ++ Builder 2009中编写多线程套接字聊天 根据我需要做的几乎完成,但我有一点问题。 我需要将TMemo *指针传递给CreateThread WinAPI函数,该函数将其向上转换为void *。

我试着这样:

HANDLE xxx = MemoChat->Handle;
hNetThread = CreateThread(NULL, 0, NetThread, xxx, 0, &dwNetThreadId);
//...

然后,在NetThread函数中,

TMemo* MyMemo((HANDLE)lpParam);
TMemo* MyMemo((TMemo*)lpParam);

但它没有用:(

问题是如何才能真正地将它正确地转发,以便我可以在这个新线程中使用我的备忘录组件?

3 个答案:

答案 0 :(得分:3)

呼叫:

TMemo*     MemoChat   = // You defined that somewhere I assume
HANDLE     hNetThread = CreateThread(NULL, 0, NetThread, MemoChat, 0, &dwNetThreadId);

这里发生的是你作为第三个参数传递的任何指针都被自动转换为void指针(或者在WinTerms LPVOID中)。没关系它没有改变它只是失去了类型信息,因为系统对你的对象一无所知。

新的主题起点:

DWORD NetThread(LPVOID lpParameter)
{
    TMemo*   MemoChat   = reinterpret_cast<TMemo*>(lpParameter);
    // Do your thread stuff here.
}

调用线程启动方法后。只需将void指针转换回正确的类型,您就可以再次开始使用它。

只是为了澄清其他误解。

HANDLE是一个指针 你可以将它作为参数传递给NetThread()。

HANDLE是指向系统控制下指针的指针,指向您正在使用的对象。那么为什么双重间接。它允许系统移动对象(并更新其指针),而无需查找对象的所有所有者。所有者都有处理指向刚刚更新的指针。

这是一种老式的计算机科学概念,在现代计算机中很少使用,因为OS /硬件能够将主存储器交换到二级存储器中。但对于某些资源,它们仍然有用。如今,当需要手柄时,它们隐藏在远离用户的物体内。

答案 1 :(得分:2)

请理解HANDLE是指针,而是Win32 API的概念。所以第一行将LPVOID强制转换为HANDLE - 这是正确的,因为线程例程的参数实际上是作为句柄(xxx)给出的。然而,它继续将HANDLE转换为MyMemo对象;这会将句柄中的位视为形成一个地址 - 它们不是。

第二行执行完全相同的转换 - 它将句柄视为直接指针。

我想知道为什么你没有将MemoChat本身传递给线程:

hNetThread = CreateThread(NULL, 0, NetThread, MemoChat, 0, &dwNetThreadId);

答案 2 :(得分:0)

这更像是尝试澄清句柄与指针的关系,因为我认为Martin并不完全正确。

“指向指针的指针”实际上称为HANDLE,是一种常见的CS方法,允许操作系统在没有应用层明确知识的情况下物理移动堆分配的内存块,应用层始终通过应用层访问它们处理。经典68K Mac OS以这种方式工作。以这种方式工作的OS通常允许用户代码通过句柄以及直接从堆中分配内存。此方法用于没有适当内存管理硬件的计算机上。

然而,HANDLE这个词的其他用途借用了之前使用的一些抽象,但具有不同的实现。不透明指针(指向用户不知情的数据结构的指针 - PIMPL惯用法)通常也称为HANDLES。

此外,术语HANDLE可以简单地用于表示对象的“引用” - 可能是数组的索引。 Unix文件句柄(=文件描述符)就是一个很好的例子。标准输入= 0,标准输出= 1,...

那么,以上哪些是Windows API HANDLES?我见过相互矛盾的报道。 This document说:

  

Win32中的句柄是用于的数字   识别资源或窗口。他们   不是指针或指针   指针。将它们视为ID号。