
現在マルチスレッドアプリケーションを作成しています。
ところが、
CreateThread(NULL, 0, listenThread, this, 0, &m_listenThreadId);
この行でエラーが出ます。
エラー内容は、
3番目の引数を'unsigned long (void *)' から 'unsigned long (__stdcall *)(void *)' に変換できません。
です。関数のポインタについてもまだよく理解していないので、このエラーの意味が良く分かりません。
どなたか、エラーの意味と解決方法を教えて頂けませんか?
コンパイラはVisual C++6.0です。
どうぞ宜しくお願いします。
A 回答 (4件)
- 最新から表示
- 回答順に表示

No.4
- 回答日時:
解決方法は他の方が示されているので、私はstdcallの事を説明します。
関数や他の言語のプロシージャ、サブルーチンなどは名前付け規約と呼び出し規約が規格上決まっています。
Visual C++ではデフォルトの規約は_cdeclであり、規約では引数を右から左に向かってスタックに積み、つんだスタックの破棄は呼び出し側で行います。
それに対して_stdcallでは呼び出し順序こそ同じですが、スタックの破棄は呼び出された側が処理する事になっています(よってykkw_2001さんの示された方法でやった場合、コンパイルは通るでしょうがスタックの整合性が保てない事になるため危険です)。
なぜこのような規約になっているかは私も不勉強のため知らないのですが、_cdecl規約の利点として可変個の引数の関数を作る事が出来る、という事です。
たとえば入門用によく使われるprintf()関数などは第一引数のchar*の内容を解析して引数の個数を調べ、その数から判断してスタックから引数を自分で取ってくるようになっています(当然積んだ個数<パラメータの数の場合、ヤバイ事になります(^^;)。
んじゃ、なぜ_stdcallがあるのか?というのはx86系CPU(互換含む)では
RET n
(nは即値、プログラムコード上で既に決まっている定数の事)
という命令があり、関数から戻るときに同時にスタックに積まれた引数を始末する事が出来るためです。
_cdeclではRET命令で戻ってきた後に呼び出し側が破棄する(といってもスタックポインタの操作だけですが)ため、速度は微妙に_stdcallのほうが早くなります。
そのため頻繁に呼び出されるWin32APIは一つのAPIを除いてすべて_stdcallで宣言されています(問題の一つはwsprintf関数です。MSDNの解説を見てみてください)。
実際には上記の呼び出し規約だけではなく、名前付け規約の方もかかってくる場合があります(CとC++を併用する場合とか)。そのへんは参考URLかMSDNを参照してください。
Helpに載っている事なので釈迦に説法かもしれませんが・・・
CreateThread APIでは標準C関数の初期化処理について問題が発生するため引数に渡す関数とそこから呼ばれる関数に標準C関数が無い事を確認してください。でないとメモリリークが発生します。
標準C関数を使いたい場合は_beginthread(), _beginthreadex()関数、 またはMFCのCWinThreadクラスをお使いください。
参考URL:http://www.microsoft.com/japan/developer/library …
No.3
- 回答日時:
MFCを使っていいのなら、
-------------------------------------
CWinThread *pThread = AfxBeginThread(
listenThread,
this);
-------------------------------------
で、スレッド作成したほうが簡単ですよ。
(listenThreadは、自作関数)
No.2
- 回答日時:
CreateThreadの3番目のパラメータは、
DWORD WINAPI ThreadFunc(LPVOID t) {}
これと同様の関数のアドレスを必要とします。
というエラーです。WINAPIを付けていないのが原因だと思います。
余談ですが、関数(へ)のポインタと言うと、
void (PointerToFunction*)(int, int);
などの、関数のアドレスを入れる変数を意味します。変数そのものがポインタで、その値はアドレスです。
No.1
- 回答日時:
CreateThread(NULL, 0, (unsigned long (__stdcall *)(void *))listenThread, this, 0, &m_listenThreadId);
じゃだめ?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語の関数のextern宣言
-
DLLファイルの逆コンパイラにつ...
-
大量のデータを読み込んで表示...
-
【C言語】全角文字の配列を、全...
-
C言語について(初心者)
-
C言語について。
-
c++でテンプレートのコードでわ...
-
C言語について。
-
VisualStudioでC++クラスを追加...
-
Windows Formアプリからコンソ...
-
visual studio 2022でのC#プロ...
-
プログラマー達は何故、プログ...
-
C言語 関数、変数の宣言について
-
c言語のリダイレクトによる円...
-
CPUが16bitでも32bitOSでコンパ...
-
0 == False はいいけど
-
プログラム言語について c言語...
-
C#でログファイルにファイルパ...
-
c言語
-
プログラミングc++を全く分か...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
最大スタックサイズを大きくす...
-
VB.netでDLLを読み込んで実行す...
-
スタック領域変更
-
printf / sprintf のスタック消...
-
_CRTIMPの意味は?
-
H8マイコン スタック領域に...
-
VC6でコンパイルでスタックの領...
-
Ethernetヘッダの取得 NDIS
-
逆ポーランド記法
-
CASLとCASL2の違いについて
-
関数呼び出しでのスタック消費量
-
スタックフレームの消滅
-
スタックのpush/pop動作について
-
gccでスタックサイズを変更する...
-
WINAPについて
-
VC++でプログラムから現在のス...
-
VC++6.0 Stack Overflow !!
-
Cプログラミングの関数電卓のア...
-
無償Borland5.51でスタックメモ...
-
OCXからのコールバックを繰り返...
おすすめ情報