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

このQ&Aに関連する最新のQ&A

A 回答 (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 …
    • good
    • 0

MFCを使っていいのなら、


-------------------------------------
CWinThread *pThread = AfxBeginThread(
listenThread,
this);
-------------------------------------
で、スレッド作成したほうが簡単ですよ。
(listenThreadは、自作関数)
    • good
    • 0

CreateThreadの3番目のパラメータは、


 DWORD WINAPI ThreadFunc(LPVOID t) {}
これと同様の関数のアドレスを必要とします。

というエラーです。WINAPIを付けていないのが原因だと思います。

余談ですが、関数(へ)のポインタと言うと、
void (PointerToFunction*)(int, int);
などの、関数のアドレスを入れる変数を意味します。変数そのものがポインタで、その値はアドレスです。
    • good
    • 0

CreateThread(NULL, 0, (unsigned long (__stdcall *)(void *))listenThread, this, 0, &m_listenThreadId);



じゃだめ?
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qエラー「invalid conversion from `void (*)()' to `void (*)(int)'」

皆様、よろしくお願いしたします。RedHat9上で
次のような「鬼ごっこのプログラム」server.cをコンパイルしています。

$ g++ -o server server.c
server.c: function 内の `void session_init(int, char, int, int, char, int,
int)':
server.c:134: invalid conversion from `void (*)()' to `void (*)(int)'

というエラーが出てしまいます。
134行というと
「 signal(SIGINT, die);」
なのですが何が間違っているんでしょうか?

Aベストアンサー

die の宣言を
void die(int sig);
にしたのであれば, session_loop の中で die を呼出すときにも引数は必要ですよ.

また, 最後の die の定義のところでも引数を取るようにしていますよね? ←念の為.

Qilink32について。'__setargv__'と'__turboFloat__'が未解決

WindowsXP+bcc32+ilink32でGLUTを使ったプログラムを書いています。
bccの設定はsetbcc.exe(http://www.cmagazine.jp/setbcc.html)を使いました。
opengl32.lib, glu32.lib, glut32.libはimplib.exe(http://blog.jyoken.net/?eid=478291)を使って作成しました。

以上の設定でbcc32付属のMakeを使ってmakeしたところ、
コンパイル後のリンクで以下のようなエラーが出てしまい困っています。
どなたか解決法を教えていただけないでしょうか?

よろしくお願いします。


---------------------
エラーの内容
---------------------
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
Error: 外部シンボル '__setargv__' が未解決(root が参照)
Error: 外部シンボル '__turboFloat' が未解決(root が参照)
---------------------

---------------------
使用しているMakefile
---------------------
CC= bcc32
LINKER= ilink32

SRCS= main.c callback.c Task.c Logger.c
OBJS= $(SRCS:.c=.obj)
TARGET= main.exe

CFLAGS= -wall -O2
LFLAGS=
LIBS= opengl32.lib glu32.lib glut32.lib

INCLUDE= -I"C:\borland\bcc55\Include"
LIB= -L"C:\borland\bcc55\Lib"


all: $(TARGET)

.SUFFIXES : .obj .c

.c.obj:
$(CC) $(CFLAGS) -c $(SRCS)

$(TARGET): $(OBJS)
$(LINKER) $(LFLAGS) $(LIB) $(OBJS),$(TARGET),,$(LIBS)
---------------------

WindowsXP+bcc32+ilink32でGLUTを使ったプログラムを書いています。
bccの設定はsetbcc.exe(http://www.cmagazine.jp/setbcc.html)を使いました。
opengl32.lib, glu32.lib, glut32.libはimplib.exe(http://blog.jyoken.net/?eid=478291)を使って作成しました。

以上の設定でbcc32付属のMakeを使ってmakeしたところ、
コンパイル後のリンクで以下のようなエラーが出てしまい困っています。
どなたか解決法を教えていただけないでしょうか?

よろしくお願いします。


---------------------
エラー...続きを読む

Aベストアンサー

BorlandのCコンパイラは、スタートアップルーチンを含むオブジェクトファイルは
ライブラリファイルの中にはアーカイブされていなくて、適切な
スタートアップ用.objファイルを別途指定してリンクしていたと思います
#bcc32.exeを使った場合はコンパイラドライバが自動でやってくれる。

質問にあるMakefileの内容を見た感じでは、そのOBJファイルを指定していませんので、
それが原因で解決できないシンボル名がでているのだと思います。
ということで、ilink32.exeでリンクする対象にそのスタートアップ用OBJファイルを
含めてやればよろしいかと。

C0なんとか.OBJという名前で、コンパイルオプションに応じていくつか
存在していたと思います。
#置かれている場所はライブラリファイルのあるディレクトリです。

Qc 文字列の終わりを示すコードは 0x00 それとも '?0' , '/0' ?

cの本を参考にプログラムをかじっているのですが、
本には '?0' と書いてあり、それで出力してみるとうまくいかず
いろいろインターネットで調べたのですが、
0x00 だとうまくいきました。
良くわからないのですが、なぜでしょう?

スミマセンおねがいします。

Aベストアンサー

文字列の最後には'\0'(NULL)が必要になります。
0x00で上手くいったのは、
NULLも「整数値の0」だからです。

Q「void ( *signal(int sig, void (*func)(int)) ) (int)」の (int)

signal関数の書式についてですが、

  void ( *signal(int sig, void (*func)(int)) ) (int);

最後に付く(int)は一体何でしょうか?
このような関数の書式ははじめて見ました。
UNIX系の何かでしょうか。
回答よろしくお願いします。

Aベストアンサー

typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t sighandler);
より後半部分のtypedefを置き換えると
sighandler_t signal(int signum, void (*sighandler)(int));
つぎに戻り値の部分のtypedefを置き換えると
void (*signal(int signum, void (*sighandler)(int)))(int);
となります。
(
sighandler_t signal(int signum, void (*sighandler)(int));
の「signal(int signum, void (*sighandler)(int))」をAと置き換えて
sighandler_t A;
からtypedefを置き換えると
void (*A)(int);
となり、Aを戻すと
void (*signal(int signum, void (*sighandler)(int)))(int);
となる。
)

typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t sighandler);
より後半部分のtypedefを置き換えると
sighandler_t signal(int signum, void (*sighandler)(int));
つぎに戻り値の部分のtypedefを置き換えると
void (*signal(int signum, void (*sighandler)(int)))(int);
となります。
(
sighandler_t signal(int signum, void (*sighandler)(int));
の「signal(int signum, void (*sighandler)(int))」をAと置き換えて
sighandler_t A;
からtypedefを置き換...続きを読む

Qvoid (*signal(int signum, void (*handler)(int)))(int);

の解釈を教えてください
最後の「(int)」については詳しくお願いします

Aベストアンサー

signalが

(1)1つ目の引数の型:int
(2)2つ目の引数の型:引数がintで戻り値がvoidである関数へのポインタ
(3)戻り値の型:引数がintで戻り値がvoidである関数へのポインタ(2と同じ)

を満たす関数である事を宣言しています。最後の(int)はsignalの戻り値の
関数ポインタがint型の引数を持つ事を示しています。

「引数がintで戻り値がvoidである関数へのポインタ」の型をHANDLERと表すと

HANDLER signal(int signum, HANDLER handler);

となります。


人気Q&Aランキング

おすすめ情報