在 C++Builder2009 中如何正确地将指针从 void* 向下转换为 TMemo*?

发布于 2024-07-09 13:24:46 字数 483 浏览 12 评论 0原文

我正在 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);

但它不起作用:(

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

I am writing multi-thread socket chat in C++Builder 2009.
It is almost complete in accordance with what I need to do but I have a little problem.
I need to pass the TMemo* pointer into CreateThread WinAPI function which upcasts it to void*.

I tryed this way:

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

and then, in NetThread function,

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

but it didn`t work:(

The question is how I can really downcast it correctly so I can use my Memo Component in this new thread?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

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

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

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

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

Please understand that a HANDLE is not a pointer, but a concept of the Win32 API. So the first line casts the LPVOID to HANDLE - this is correct, as the parameter of the thread routine really is given as a handle (xxx). However, it then goes on converting the HANDLE to a MyMemo object; this treats the bits in the handle as if they would form an address - which they aren't.

The second line does exactly the same conversion - it treats a handle as if it were a pointer directly.

I wonder why you aren't passing MemoChat itself to the thread:

hNetThread = CreateThread(NULL, 0, NetThread, MemoChat, 0, &dwNetThreadId);
天涯离梦残月幽梦 2024-07-16 13:24:46

调用:

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 是一个指向系统控制下的指针的指针,它指向您正在使用的对象。 那么为什么要使用双重间接呢? 它允许系统移动对象(并更新其指针),而无需找到对象的所有所有者。 所有者都有指向刚刚更新的指针的句柄。

这是一个老式的计算机科学概念,由于操作系统/硬件能够将主内存交换到辅助存储,因此在现代计算机中很少使用。 但对于某些资源它们仍然有用。 如今,当需要手柄时,它们被隐藏在远离用户的物体内部。

Call:

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

What is happening here is that any pointer you pass as the third parameter is being auto converted into a void pointer (or in WinTerms LPVOID). That's fine it does not change it it just loses the type information as the system does not know anything about your object.

The new Thread Start point:

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

Once your thread start method is called. Just convert the void pointer back into the correct type and you should be able to start using it again.

Just to clear up other misconceptions.

A HANDLE is a pointer.
And you could have passed it as the parameter to the NetThread().

A HANDLE is a pointer to pointer under system control which points at the object you are using. So why the double indirection. It allows the system to move the object (and update its pointer) without finding all owners of the object. The owners all have handles that point at the pointer that was just updated.

It is an old fashioned computer science concept that is used infrequently in modern computers because of the OS/Hardware ability to swap main memory into secondary storage. but for certain resource they are still useful. Nowadays when handles are required they are hidden inside objects away from the user.

春风十里 2024-07-16 13:24:46

这更多是为了尝试澄清句柄与指针的问题,因为我认为 Martin 的说法并不完全正确。

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

然而,HANDLE 这个词还有其他用法,它们借用了先前用法的一些抽象,但具有不同的实现。 不透明指针(指向用户不了解的数据结构的指针 - PIMPL 习惯用法)通常也称为句柄。

此外,术语“句柄”可以简单地用来表示对对象的“引用”——可能是数组的索引。 Unix 文件句柄(= 文件描述符)就是一个很好的例子。 stdin=0,stdout=1,...

那么,上面哪些是 Windows API HANDLES? 我看到过相互矛盾的报道。 本文档说:

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

This is more to try and clarify the handle vs. pointer thing, because I don't think Martin has it exactly right.

A "pointer to a pointer" is indeed called a HANDLE, and is a common CS approach to allowing the operating system to physically move heap-allocated memory blocks around without the explicit knowledge of an application layer, which always accesses them via handles. Classic 68K Mac OS works in this way. OS'es that work in this way typically allow user code to allocate memory via handles as well as directly off the heap. This approach is used on machines that don't have proper memory-management hardware.

However,there are other uses of the word HANDLE which borrow the some of the abstraction of the previous use, but with different implementations. Opaque pointers (pointers to datastructures of which the user has no knowledge - PIMPL idiom) are also commonly called HANDLES.

Also, the term HANDLE can be used simply to denote a "reference" to an object - maybe an index into an array. Unix File Handles (= file descriptors) are a good example of this. stdin=0,stdout=1,...

So, which of the above are Windows API HANDLES? I've seen conflicting reports. This document says:

Handles in Win32 are numbers used to
identify resources or windows. They
are not pointers or pointers to
pointers. Think of them as ID numbers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文