Как я могу правильно уменьшить указатель с void * на TMemo * в C ++ Builder2009? - PullRequest
2 голосов
/ 08 ноября 2008

Я пишу многопоточный сокет-чат в 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 ]

3 голосов
/ 08 ноября 2008

Звоните:

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 обратно в правильный тип, и вы сможете снова его использовать.

Просто чтобы прояснить другие заблуждения.

A РУЧКА - это указатель .
И вы могли бы передать его в качестве параметра в NetThread ().

РУЧКА - это указатель на указатель под управлением системы, который указывает на объект, который вы используете. Так почему двойная косвенность. Это позволяет системе перемещать объект (и обновлять его указатель), не находя всех владельцев объекта. У всех владельцев есть маркеры, которые указывают на только что обновленный указатель.

Это старомодная концепция информатики, которая редко используется в современных компьютерах из-за способности ОС / оборудования переставлять основную память во вторичное хранилище. но для определенного ресурса они все еще полезны. В настоящее время, когда требуются ручки, они скрыты внутри объектов подальше от пользователя.

2 голосов
/ 08 ноября 2008

Пожалуйста, поймите, что РУЧКА является не указателем, а концепцией Win32 API. Таким образом, первая строка приводит LPVOID к HANDLE - это правильно, поскольку параметр подпрограммы потока действительно задан как дескриптор (xxx). Однако затем он продолжает преобразовывать HANDLE в объект MyMemo; это обрабатывает биты в дескрипторе так, как если бы они формировали адрес - а это не так.

Вторая строка выполняет точно такое же преобразование - обрабатывает дескриптор, как если бы он был указателем напрямую.

Интересно, почему вы не передаете сам MemoChat в ветку:

hNetThread = CreateThread(NULL, 0, NetThread, MemoChat, 0, &dwNetThreadId);
0 голосов
/ 09 ноября 2008

Это больше, чтобы попытаться уточнить, что такое дескриптор и указатель, потому что я не думаю, что у Мартина все в порядке.

«Указатель на указатель» действительно называется HANDLE и представляет собой общий подход CS, позволяющий операционной системе физически перемещать блоки памяти, выделенные в куче, без явного знания прикладного уровня, который всегда обращается к ним через ручки. Классическая 68K Mac OS работает таким образом. Операционные системы, которые работают таким образом, обычно позволяют пользовательскому коду распределять память через дескрипторы, а также напрямую из кучи. Этот подход используется на машинах, на которых отсутствует надлежащее оборудование для управления памятью.

Однако есть и другие варианты использования слова HANDLE, которые заимствуют некоторые абстракции предыдущего использования, но с другими реализациями. Непрозрачные указатели (указатели на структуры данных, о которых пользователь ничего не знает - идиома PIMPL) также обычно называют РУЧКАМИ.

Кроме того, термин HANDLE можно использовать просто для обозначения «ссылки» на объект - возможно, индекса в массиве. Файловые дескрипторы Unix (= файловые дескрипторы) являются хорошим примером этого. STDIN = 0, STDOUT = 1, ...

Итак, что из перечисленного является РУЧКОЙ Windows API? Я видел противоречивые сообщения. В этом документе говорится:

Дескрипторы в Win32 - это числа, используемые для определить ресурсы или окна. Oни не указатели или указатели на указатели. Думайте о них как о идентификационных номерах.

...