6

MFC を使用してスレッドを作成する方法を示すサンプル コードでは、スレッド関数を static と__cdecl. なぜ後者が必要なのですか?ブースト スレッドはこの規則を気にしないので、それは単なる時代錯誤ですか?

例 (MFC):

static __cdecl UINT MyFunc(LPVOID pParam)
{
...
}

CWinThread* pThread = AfxBeginThread(MyFunc, ...);

一方、ブースト:

static void func()
{
...
}

boost::thread t;
t.create(&func);

(私は IDE の近くにいないので、コード サンプルは 100% 正しいとは限りません)。

__cdecl のポイントは何ですか? スレッドを作成するときにどのように役立ちますか?

4

5 に答える 5

4

__cdecl は、C 呼び出し規約を使用するようにコンパイラーに指示します (stdcall、fastcall、またはコンパイラーがサポートするその他の呼び出し規約とは対照的に)。VC++ はデフォルトで stdcall を使用していると思います。

呼び出し規約は、引数をスタック (または fastcall の場合はレジスタ) にプッシュする方法や、スタックから引数をポップするユーザー (呼び出し元または呼び出し先) などに影響します。

ブーストの場合。テンプレートの特殊化を使用して、適切な関数の型と呼び出し規約を把握していると思います。

于 2008-10-04T14:11:59.527 に答える
4

のプロトタイプを見てくださいAfxBeginThread():

CWinThread* AfxBeginThread(
   AFX_THREADPROC pfnThreadProc,
   LPVOID pParam,
   int nPriority = THREAD_PRIORITY_NORMAL,
   UINT nStackSize = 0,
   DWORD dwCreateFlags = 0,
   LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL 
);

AFX_THREADPROCの typedef ですUINT(AFX_CDECL*)(LPVOID)。関数を に渡すときはAfxBeginThread()、呼び出し規約を含め、そのプロトタイプと一致する必要があります。

__cdeclおよび__stdcall(__fastcallおよび および)の MSDN ページで__thiscallは、各呼び出し規則の長所と短所について説明しています。

コンストラクターはテンプレートを使用して、boost::thread関数ポインターまたは呼び出し可能な関数オブジェクトを渡すことができるようにするため、MFC と同じ制限はありません。

于 2008-10-04T14:15:54.480 に答える
1

C/C++ コンパイラは、デフォルトで C 呼び出し規約 (一番右のパラメーターをスタックに最初にプッシュする) を使用します。これは、可変引数番号を持つ関数を printf として操作できるようにするためです。

Pascal 呼び出し規則 (別名 "fastcall") では、左端のパラメーターが最初にプッシュされます。これはより高速ですが、簡単な可変引数関数の可能性を犠牲にします(いくつかのトリックを使用する必要がありますが、まだ可能であるとどこかで読みました)。

Pascal 規則を使用すると速度が向上するため、Win32 と MacOS の両方の API は、特定の場合を除き、デフォルトでその呼び出し規則を使用します。

その関数にパラメーターが 1 つしかない場合、理論的にはどちらの呼び出し規則を使用しても問題ありませんが、問題を回避するためにコンパイラが同じ呼び出し規則を強制する場合があります。

ブースト ライブラリは移植性を考慮して設計されているため、特定のコンパイラが使用している呼び出し元の規約に依存しない必要があります。

于 2008-10-04T16:17:53.953 に答える
1

スレッドは、これを管理するランタイム関数によって呼び出され、その関数はそのようになることを期待しているためです。Boostは別の方法で設計しました。

スレッド関数の先頭にブレークポイントを置き、呼び出されたときにスタックを確認すると、呼び出し元のランタイム関数が表示されます。

于 2008-10-04T14:10:53.850 に答える
1

本当の答えは、windows がスレッド proc ルーチンを内部的に呼び出す方法に関係しており、関数が特定の呼び出し規則に従うことを期待しています。

#define WINAPI      __stdcall

これは、呼び出された関数がスタックのクリーンアップを担当することを意味します。boost::thread が任意の関数をサポートできる理由は、thread::create 関数の呼び出しで使用される関数オブジェクトへのポインターを CreateThread に渡すためです。スレッドに関連付けられた threadproc は、関数オブジェクトで operator() を呼び出すだけです。

したがって、MFC が __cdecl を必要とする理由は、AfxBeginThread への呼び出しに渡された関数を内部的に呼び出す方法に関係しています。vararg パラメーターを許可することを計画していない限り、これを行う正当な理由はありません...

于 2008-10-17T22:19:50.600 に答える