C++プログラムの引数についての質問
- C++プログラムの引数について質問があります。
- 具体的な質問内容は、'_beginthread'のエラーメッセージに関してです。
- エラーメッセージが発生しており、引数の変換に関する問題があるようです。
- ベストアンサー
beginthread 引数
#include <windows.h> #include <process.h> class CPti4Dlg::public CDialog { public: void test(void*); } void CPti4Dlg::test(void *) { long ret; float data[4]; ret = PtMultiInputEx(m_Id, 4, data); if(ret != 0) { ErrorHandling("PtMultiInputEx", ret); if(ret != 20102){ return; } } m_Edit_Ch0 = data[0]; m_Edit_Ch1 = data[1]; m_Edit_Ch2 = data[2]; m_Edit_Ch3 = data[3]; UpdateData(FALSE); } void CPti4Dlg::OnButtonInput() { _beginthread(&CPti4Dlg::test,0,NULL); m_Edit_Ret.SetWindowText("入力処理:正常終了"); } error C2664: '_beginthread' : 1 番目の引数を 'void (__thiscall CPti4Dlg::* )(void *)' から 'void (__cdecl *)(void *)' に変換できません。(新しい機能 ; ヘルプを参照) ------------------------------------------------------------------------------ これ問題全然ないです。 void CPti4Dlg::OnButtonInput() { long ret; float data[4]; ret = PtMultiInputEx(m_Id, 4, data); if(ret != 0) { ErrorHandling("PtMultiInputEx", ret); if(ret != 20102){ return; } } m_Edit_Ch0 = data[0]; m_Edit_Ch1 = data[1]; m_Edit_Ch2 = data[2]; m_Edit_Ch3 = data[3]; UpdateData(FALSE); m_Edit_Ret.SetWindowText("入力処理:正常終了"); }
- lysander627
- お礼率60% (3/5)
- C・C++・C#
- 回答数5
- ありがとう数4
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
> コンパイルエラーの原因はCPti4Dlgクラスのメンバーはstaticでなないです。 > ret = PtMultiInputEx(m_Id, 4, data)の中で > PtMultiInputEx は ハードウェアメーカは カプセル化関数なんですけど、定義されていないです。。。 定義されていない? DLLやLibで提供されていないということですか … でもボタンのクリックイベントでは使えたんですよね
その他の回答 (4)
- redfox63
- ベストアンサー率71% (1325/1856)
CWinThreadの派生クラスで AfxBeginThreadで行ったほうがいいかも また 制御関数は CPti4Dlgクラスのメンバーにするなら static関数にする必要があります 一般的には クラス外に定義したグローバル関数を使う手法を使います staticや外部関数にした場合 クラスのメンバーに直接アクセスする手段がなくなるので スレッド起動時の引数に thisポインタなどを与えます また クラスのメンバーへのアクセスですがウィンドウメッセージをRegisterWindowMessageなどで 定義したものを PostMessageなどで投げてやるような仕組みが必要になってきます また受け側のCPti4Dlgクラスのメッセージマップには ON_MESSAGEマクロなどで受け入れ態勢が必要ですが
お礼
どうもありがとうございました。 コンパイルエラーの原因はCPti4Dlgクラスのメンバーはstaticでなないです。 ret = PtMultiInputEx(m_Id, 4, data)の中で PtMultiInputEx は ハードウェアメーカは カプセル化関数なんですけど、定義されていないです。。。 これどうしたらいいですが。。。
補足
redfox63さん言った通りにいろいろ調べましたが、PostMessageたぶん完成できると思います。 ちょっと詳しい直してもらえますか
- Wr5
- ベストアンサー率53% (2177/4070)
>PtMultiInputEx 関数は ハードウェアメーカで カプセル化した関数です。 で、その関数はスレッドセーフなんですか? # 「スレッドセーフとは」で検索。 # http://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%AC%E3%83%83%E3%83%89%E3%82%BB%E3%83%BC%E3%83%95 まぁ、実際に走るスレッドが1つだけ…であればとりあえずは大丈夫かもしれませんが……。 >class CPti4Dlg : public CDialog >{float m_Edit_Ch0; >float m_Edit_Ch1; >float m_Edit_Ch2; >float m_Edit_Ch3; } >四つのデータを表示する用edit control box です。 エデットコントロールに紐付いている…んですよね? floatで使えたかはちょっと判りませんが……。 >UpdateData(FALSE) -> データをリアルタイムで出ってます。 でしたら、作成したスレッド関数は1回まわったら抜ける。ではダメかと。 停止に関してはイベントオブジェクトなどでUIスレッドからワーカースレッドに通知するようにして、通知を受けた時点でワーカースレッドが終了するように作る必要があるでしょう。 通知を受けるまではループで回し続ける必要があります。 # とは言え、全力全開で回す必要はないでしょうから適度にSleep()でもかまして下さい。 「スレッド 同期処理」とかで検索してください。 使用例とか見つかるかと思われます。 # あと…スレッド開始したら「Inputボタン」とやらは無効(EnableWindow()など)にしておかないと、複数のスレッドが起動してしまうのでご注意を。 ## スレッドセーフで無かった場合は…ここら辺で不具合が出るかも知れません。 で……… クラスのメンバにアクセスする為にはthisポインタが必要だったハズです。 # それが「どのインスタンスの」という部分です。 現状ではそれを渡していませんのでコンパイル時などにエラーになるかと。 鈴木さん、佐藤さん、田中さんがそれぞれ「連絡帳」を持っています。 先生が「連絡帳に○○を記入して下さい」と指示すれば、ぞれぞれ「自分の連絡帳」に記入するでしょう。 現状では、所有者不明の連絡帳に「記入して」と言っているようなものです。 所有者がいない連絡帳なのか、鈴木さんの連絡帳に記入したらいいのか判りませんよね? ということで、スレッドで動作している関数に何らかの方法でthisポインタを渡す必要があるでしょう。 http://typea.info/tips/wiki.cgi?page=MFC+%A5%DE%A5%EB%A5%C1%A5%B9%A5%EC%A5%C3%A5%C9 とか、参考になりますかね…… # スレッドの起動方法とthisポインタの渡し方、static関数にする。とか…。
- Wr5
- ベストアンサー率53% (2177/4070)
質問内容すら書けない…という状況で自分でデバッグできるのだろーか… C++やMFCはちゃんと使えるワケではないですが…… >error C2664: '_beginthread' : 1 番目の引数を 'void (__thiscall CPti4Dlg::* )(void *)' から 'void (__cdecl *)(void *)' に変換できません。 staticでないメンバ関数をスレッドの開始として使えましたかね? http://d.hatena.ne.jp/kasei_san/20070612/p1 まぁ、呼び出し規約の問題でもあるみたいですが… で、thisポインタも渡せていない状態で… >ret = PtMultiInputEx(m_Id, 4, data); >m_Edit_Ch0 = data[0]; >m_Edit_Ch1 = data[1]; >m_Edit_Ch2 = data[2]; >m_Edit_Ch3 = data[3]; 「どのインスタンスの」メンバ変数なんでしょ? >UpdateData(FALSE); ドコに(どのインスタンス)対して実行したらいいんでしょう?
お礼
ご回答ありがとうございました。 質問書いてなかった、すみません。 実際に、これがセンサから4チャネルデータを読み出すのプログラムです。 PtMultiInputEx 関数は ハードウェアメーカで カプセル化した関数です。 class CPti4Dlg : public CDialog { float m_Edit_Ch0; float m_Edit_Ch1; float m_Edit_Ch2; float m_Edit_Ch3; } 四つのデータを表示する用edit control box です。 UpdateData(FALSE) -> データをリアルタイムで出ってます。 二つのボタンを使いたいです。intput を押して、データを連続的に読み取ります、stopを押して、動作を停止します。 今、threadで使って、問題ある状態で、手伝ってありがとうございました。 もしもっと詳しく直していただければ、幸いでございます。
- Tacosan
- ベストアンサー率23% (3656/15482)
超能力を持たない人にも質問がわかるように書いてください.
関連するQ&A
- 閉じてしまったダイアログのエディットボックスへの書き込み禁止方法
VC++ 6.0 MFC ダイアログベースです。 メインダイアログ画面で、ボタンを押下した時に、別ダイアログ(子ダイアログ)が呼び出されて、 その子ダイアログ内では、ワーカースレッドを使用して処理を行い、 処理結果をエディットボックスに表示させています。 子ダイアログを閉じる時に、WaitForSingleObject を使って、スレッドを完全に終了させてからダイアログを閉じるように しているのですが、スレッドの処理が、エディットボックスに書き込む時に閉じてしまうと、 スレッドがそこで止まってしまいスレッドが終了しません。 このような場合どうしたら良いのでしょうか? ・閉じるボタンが押されたら、エディットボックスに書き込まないようにすれば良いと思い、 (フラグを立てて試したのですが、フラグチェック後に閉じるが押されることがあり失敗) // スレッドの開始 m_Thread = AfxBeginThread(ThreadFunc, this); // この時、子ダイアログを閉じてしまうと // INFINITEなので、ずっと止まってしまいます。 CString data = "処理結果"; case 0: m_M0edit.SetWindowText(data); break; case 1: m_M1edit.SetWindowText(data); break; case 2: m_M2edit.SetWindowText(data); break; ・ ・ ・ ・ // 子ダイアログを閉じる時に呼び出されます。 // スレッドでの処理が完全に終わるのを待ちます。 afx_msg void CSelecting_Dlg::OnClose() { DWORD dwRet dwRet = WaitForSingleObject(m_Thread->m_hThread, INFINITE); EndDialog(0); } /***************/ 失敗談 /***************/ // スレッドの開始 m_Thread = AfxBeginThread(ThreadFunc, this); // この時、子ダイアログを閉じてしまうと // INFINITEなので、ずっと止まってしまいます。 CString data = "処理結果"; if (m_openFlag == 1){ //フラグを見て書き込みするかチェックする。 switch (t){ case 0: m_M0edit.SetWindowText(data); break; case 1: m_M1edit.SetWindowText(data); break; case 2: m_M2edit.SetWindowText(data); break; ・ ・ ・ ・ } } // 子ダイアログを閉じる時に呼び出されます。 // スレッドでの処理が完全に終わるのを待ちます。 afx_msg void CSelecting_Dlg::OnClose() { DWORD dwRet m_openFlag = false; //閉じるボタンが押されたら フラグを降ろす。 dwRet = WaitForSingleObject(m_Thread->m_hThread, INFINITE); EndDialog(0); }
- ベストアンサー
- C・C++・C#
- 別ソースファイルからの呼び出し
現在VC++6.0でプログラムをしています。 そこで基本的な質問かもしれないのですが 別のソースファイルからの呼び出しはどのようにおこなえばいいのでしょうか?具体的には 前略 void CDioBitDlg::OnButtonAioInputDiBit() { //デジタル入力 UpdateData(TRUE); short DiData; Ret = AioInputDiBit(Id, m_DioBit, &DiData); if(Ret != 0){ Ret2 = AioGetErrorString(Ret, ErrorString); TextString.Format("AioInputDiBit = %d : %s", Ret, ErrorString); m_ErrorString.SetWindowText(TextString); return; } TextString.Format("入力データ : %d", DiData); m_DioData.SetWindowText(TextString); m_ErrorString.SetWindowText("デジタル入力 : 正常終了"); } 後略 別のソース 前略 void CSimulatorWnd::OnPaint() { CPaintDC dc(this); //描写用のデバイスコンテキスト CRect cr; GetClientRect(&cr); dc.FillSolidRect(cr, RGB(0,0,0)); } 後略 前述のは入力信号をデジタルの1もしくは0で表示するダイアログプログラムなのですが この1もしくは0の値を後述のソースファイルに持ってくる場合どのようにすればよいのでしょうか?
- 締切済み
- C・C++・C#
- DLLの関数呼び出しで引数があるとフリーズしてしまう。
はじめまして、C言語勉強中の初心者です。 現在、DLLに定義されている関数を呼び出すことを試していますが、うまくいかないので質問させて頂きました。 DLLには2つの関数が定義されています。 1.void Hello() 2.void HelloEx(char *pval); 1の関数を呼び出す場合は異常なく終了するのですが、2の関数を呼び出すと、フリーズしてしまいます。 フリーズする原因が分からないので、教えて頂ければと思います。 以下にソースを掲載します。 因みにコンパイラはBCC5.5.1を使用しています。 ***************************************************** DLL(Hello.c) [bcc32 -WD Hello.c] ***************************************************** #include <windows.h> #include <stdio.h> __declspec(dllexport) void CALLBACK Hello(void) { printf("Hello!\n"); } __declspec(dllexport) void CALLBACK HelloEx(char *pVal) { printf("Hello!%s\n", pVal); } ***************************************************** EXE(HelloTest.c)[bcc32 -L HelloTest.c] ***************************************************** #include <windows.h> #include <stdio.h> typedef void (*Hello)(void); typedef void (*HelloEx)(char*); int main(void) { HMODULE hMod; Hello func; HelloEx funcEx; hMod = LoadLibrary( "Hello.dll" ); if(!hMod) return FALSE; func = (Hello)GetProcAddress( hMod, "Hello"); if(!func) return FALSE; funcEx = (HelloEx)GetProcAddress( hMod, "HelloEx"); if(!funcEx) return FALSE; func(); funcEx("World"); FreeLibrary(hMod); return 0; } *********************************************** 以上
- ベストアンサー
- C・C++・C#
- _beginthreadにて発生するコンパイルエラーについて
過去に近い質問が出ていましたが、探しているような回答が見つからなかったので質問させていただきます。 プログラム作成の過程で_beginthreadを使うことになったのですが、以下のエラーメッセージが表示されます。 error C2664: '_beginthread' : 1 番目の引数を 'void (unsigned long)' から 'void (__cdecl *)(void *)' に変換できません。 (新しい機能 ; ヘルプを参照) スコープ内でこの名前を持つ関数でターゲット型に一致するものはありません 調べた限りC++で作成している為Cでコンパイルされた関数を呼び出す為にC++で指示する必要がある、という事は理解できたのですが、いまいち修正の方法が判りません。 下記に関連部分ソースの一部と開発環境を記載します。 どなたかご教授の方よろしくお願いいたします。 開発環境:Visual C++6.0 プロジェクトの設定でランタイムライブラリはマルチスレッドに設定済み。 WINAPIとして作成、指定URLに接続するためのスレッドを作成したい -------------------グローバル一部--------------- DWORD cthread=0; //グローバルで宣言している addurl[1]; -----------問題の処理WndProc内部(メイン部)--------- addurl[0]=url; //編集したアドレスを貼り付け cthread=_beginthread(OpenURL,0,0); //ここでエラー -----------送る先(OpenURL)------------- void __cdecl OpenURL(DWORD index) { BASS_StreamFree(chan); // close old stream SendMessage(Edit,WM_SETTEXT,0,"connecting..."); if (!(chan=BASS_StreamCreateURL(addurl[index],0,BASS_STREAM_META|BASS_STREAM_STATUS,StatusProc,0))) { SendMessage(Edit,WM_SETTEXT,0,"not playing"); Error("Can't play the stream"); --------------以下省略---------------
- ベストアンサー
- C・C++・C#
- 例外処理(初回)についてのご質問
プログラムを実行させた時、下記の様なメッセージが出力されたあとに、特定の場所でエラーが出てしまいます。 色々と試して見たのですが、解決出来ずに困っております。何方かどの辺を調べれば良いか等のアドバイスをお願い致します。 <エラーメッセージ> "例外処理 (初回) は XXXX.exe (MFC42D.DLL) にあります: 0xC0000005: Access Violation。" <停止場所> CWnd* CWnd::GetDlgItem(int nID) const { ここです→ASSERT(::IsWindow(m_hWnd)); if (m_pCtrlCont == NULL) return CWnd::FromHandle(::GetDlgItem(m_hWnd, nID)); else return m_pCtrlCont->GetDlgItem(nID); } <エラーが発生するプログラム> BOOL CComProgramDlg::BinarySend(BYTE SendData[], unsigned long SendLength) { int Ret; unsigned long Len; ここら辺です→CStatic* pStic1 = (CStatic*)GetDlgItem(IDC_MSG_STATIC); Ret = WriteFile(m_hComm, &SendData[0], SendLength, &Len, NULL); if(!Ret) return(FALSE); if(SendLength > Len) return(FALSE); pStic1 -> SetWindowText("データを送信しました。"); return(TRUE); } 上記はデータシリアル通信の送信用で10回程度、このメンバ関数を通した時に急に発生します。 よろしくお願いいたします。
- ベストアンサー
- C・C++・C#
- エディットボックスのテキストが表示されないのはなぜですか
VC++初心者です。 以下のソースでエディットボックスのテキストが表示されません。というか、最後のループの時のみ表示されますが、一回一回表示するにはどうしたらいいでしょうか? void CCRPTC_accessDlg::OnBnClickedOk() { int i; CEdit* myEdit1 = (CEdit*)GetDlgItem(IDC_EDIT1); ・ ・ ・ for (i=1;i<10;i++){ if (Ret != SUCCESS) { myEdit1->SetWindowText("NG!"); } else { myEdit1->SetWindowText("OK!"); } } }
- ベストアンサー
- C・C++・C#
- 記憶クラス(関数の引数をなくして外部変数を利用しての書き換え)
/*入力した価格の合計とその税込価格を求めるプログラム*/ #include<stdio.h> #define TAX 0.05 float Getsyouhizeigaku(float); void main(void) { float price, total = 0.0; float zeigaku; while(1){ printf("Price? (finish -> -1)\n"); scanf("%f", &price); if(price == -1.0) break; total += price; } zeigaku = Getsyouhizeigaku(total); printf("価格 %.0f 円の場合, 消費税込み価格は %.0f 円\n", total, zeigaku); } float Getsyouhizeigaku(float kakaku) { float zeikomikakaku; zeikomikakaku = kakaku * (1.00 + TAX); return(zeikomikakaku); } このプログラムを関数の引数(価格を表す実数)をなくし、外部変数を利用して同じ処理を行うようにプログラムを変更せよ。 という問題で #include<stdio.h> #define TAX 0.05 float Getsyouhizeigaku(void); void main(void) { float price, total = 0.0; float zeigaku; while(1){ printf("Price? (finish -> -1)\n"); scanf("%f", &price); if(price == -1.0) break; total += price; } zeigaku = Getsyouhizeigaku(); printf("価格 %.0f 円の場合, 消費税込み価格は %.0f 円\n", total, zeigaku); } float Getsyouhizeigaku(void) { extern float total; float zeikomikakaku; zeikomikakaku = total * (1.00 + TAX); return(zeikomikakaku); } と変更してコンパイルしたところ「'_total'が未解決です」と出ました。何が問題なのかわかりません。 わかる方いましたらよろしくお願いします。
- 締切済み
- C・C++・C#
- 変数の代入について
ダイアログベースで、ダイアログ1からダイアログ2を開きダイアログ1のエディットボックスのデータをダイアログ2に表示する下記コードを教わりました。 変更後のようにしても問題ないと思いましたが、'dlg' は定義されていない識別子です。とエラーが出ます。 どうしてなのかお教えていただきたいのですが、 よろしくお願いします。 <変更前> CSubDlg dlg2; dlg2.m_strText = strText; dlg2.DoModal(); <変更後> void CSubDlg::OnPaint() { m_strText = dlg.strText; ちなみにdlgはウィザードが作ったコードで、 CMainDlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); ダイアログ1のことだと思うのですが。。。。 ************************** メインダイアログとしてCMainDlgを例にしますが、かなり割愛します。 このダイアログには、Editが貼り付けられているとします。Editコントロールに割り当てたIDをIDC_EDIT_INPUTだと仮定します。 DDXとかのデータ変換を使う方法もありますが、ここでは単にデータを取得します。 // // OKボタンが押された時の処理 // void CMainDlg::OnOK() { // データの取得 CString strText; GetDlgItemText(IDC_EDIT_INPUT, strText); CSubDlg dlg2; dlg2.m_strText = strText; dlg2.DoModal(); } class CSubDlg : pbulic CDialog { public: CString m_strText; // 親から渡される文字列を格納する変数 ・ ・ ・ ・ ・ }; あとは、CSubDlgのOnPaintでテキストを描画します。 void CSubDlg::OnPaint() { // テキストをクライアント領域の中央に描画 CRect rect; GetClientRect(rect); CPaintDC dc(this); dc.TextOut(m_strText, rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); }
- ベストアンサー
- C・C++・C#
- 文字変換方法について
VC++6.0にて勉強中の初心者です。 現在、テキストエディタ1(例:"H")とテキストエディタ2("0001")に入力した文字列を16進変換し、テーブル(例:cmd)に格納し、テキストエディタ3には、1,2で入力した文字列を表示したいのですが、どのようにすればよいでしょうか? 下記のように考えてみましたが、ご指導お願い致します。 void CMogiver1Dlg::OnOK() { int cmd; UpdateData(TRUE); if(( m_text1 == _T("H") ) && (m_text2 == _T("0001"))){ cmd = atoi(m_text1); cmd = 0x38; //テキストエディタ1.2の条件が合えば、8を表示する。 m_text3 = cmd; } UpdateData(FALSE);
- ベストアンサー
- C・C++・C#
- UpdateData( FALSE); による文字列データの表示更新(VC++6.0)
VC++の超初心者です. UpdateData( FALSE ); を用いてエディットボックスの文字列の表示の更新を 試みているのですが,たとえば,以下のコードのようにボタンをクリックした際に文字列表示の更新を複数回行おうとするとうまくいきません. 具体的には一回目のUpdateData( FALSE );が反映されず二回目のUpdateData( FALSE );のみ反映されるという症状です. なおm_mojiretsuはCstring型でエディットボックスのDDX用の変数です. void CMyDlg::OnButton1() { DWORD p; m_mojiretsu=_T("mojirstu1"); UpdateData( FALSE ); /*5秒の待ち*/ p=timeGetTime(); while(1){if((timeGetTime()-p)>5000) break;} m_mojiretsu=_T("mojirstu1\r\nmojirstu2"); UpdateData( FALSE ); } 何か別の処理を行わなければいけないのでしょうか. どこかに根本的なミスがあるのでしょうか. VC歴3日程度で,右も左も分からず大変困っております.よろしくお願いします.
- ベストアンサー
- C・C++・C#
お礼
すいません。 DLLやLib提供されていますが、コードカプセル化状態です。 UpdateData関数もこの問題です。