2

C++Builder 2009 でマルチスレッド ソケット チャットを作成し
ています。必要な作業はほぼ完了していますが、少し問題があります。TMemo* ポインターを void* にアップキャストする CreateThread WinAPI 関数に渡す必要があります。

私はこの方法を試しました:

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

そして、NetThread 関数で、

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

しかし、うまくいきませんでした:(

問題は、この新しいスレッドでメモ コンポーネントを使用できるように、正しくダウンキャストするにはどうすればよいかということです。

4

3 に答える 3

3

電話:

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

ここで起こっていることは、3 番目のパラメーターとして渡すポインターは、void ポインター (または WinTerms LPVOID) に自動変換されるということです。システムはあなたのオブジェクトについて何も知らないので、型情報を失うだけです。

新しいスレッド開始点:

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

スレッド開始メソッドが呼び出されたら。void ポインターを正しい型に変換するだけで、再び使用できるようになります。

他の誤解を解くためだけに。

HANDLE はポインターです。
そして、それをパラメーターとして NetThread() に渡すこともできました。

HANDLE は、使用しているオブジェクトを指すシステム制御下のポインターへのポインターです。では、なぜ二重間接化なのか。これにより、システムは、オブジェクトのすべての所有者を見つけることなく、オブジェクトを移動 (およびそのポインターを更新) できます。所有者はすべて、更新されたばかりのポインターを指すハンドルを持っています。

これは、OS/ハードウェアがメイン メモリをセカンダリ ストレージにスワップできるため、最近のコンピュータではめったに使用されない、昔ながらのコンピュータ サイエンスの概念です。しかし、特定のリソースについては、それらはまだ役に立ちます。現在、ハンドルが必要な場合、ハンドルはユーザーから離れたオブジェクト内に隠されています。

于 2008-11-08T18:50:09.053 に答える
2

HANDLE はポインターではなく、Win32 API の概念であることを理解してください。したがって、最初の行は LPVOID を HANDLE にキャストします。スレッド ルーチンのパラメータは実際にはハンドル (xxx) として指定されるため、これは正しいです。ただし、HANDLE を MyMemo オブジェクトに変換し続けます。これは、ハンドル内のビットをアドレスを形成するかのように扱いますが、そうではありません。

2 行目はまったく同じ変換を行います。ハンドルを直接のポインターであるかのように扱います。

なぜ MemoChat 自体をスレッドに渡さないのだろうか:

hNetThread = CreateThread(NULL, 0, NetThread, MemoChat, 0, &dwNetThreadId);
于 2008-11-08T15:59:39.070 に答える
0

これは、ハンドルとポインターの違いを明確にするためのものです。Martin が正確に理解しているとは思えないからです。

「ポインターへのポインター」は実際には HANDLE と呼ばれ、オペレーティング システムがヒープに割り当てられたメモリ ブロックを物理的に移動できるようにするための一般的な CS アプローチであり、常にハンドルを介してアプリケーション層にアクセスします。Classic 68K Mac OS はこのように動作します。この方法で動作する OS は通常、ユーザー コードがハンドルを介してメモリを割り当てたり、ヒープから直接メモリを割り当てたりできるようにします。このアプローチは、適切なメモリ管理ハードウェアを持たないマシンで使用されます。

ただし、以前の使用の抽象化の一部を借用した HANDLE という単語の他の使用法がありますが、実装は異なります。不透明なポインター (ユーザーが知らないデータ構造へのポインター - PIMPL イディオム) も、一般に HANDLES と呼ばれます。

また、HANDLE という用語は、単にオブジェクトへの「参照」を示すために使用できます。おそらく、配列へのインデックスです。Unix ファイル ハンドル (= ファイル記述子) は、この良い例です。標準入力=0、標準出力=1、...

では、上記のうちどれが Windows API ハンドルですか? 相反する報告を見てきました。この文書には次のように書かれています。

Win32 のハンドルは、リソースまたはウィンドウを識別するために使用される番号です。それらは、ポインターまたはポインターへのポインターではありません。それらをID番号と考えてください。

于 2008-11-08T23:24:10.980 に答える