DLLをGetProcAddress()で実行できない

このQ&Aのポイント
  • dllの操作の練習中に、GetProcAddress()でDLLを実行できない問題が発生しています。
  • 解決策としては、インポートライブラリをリンクさせることでうまく動作することができます。
  • しかし、明示的にdllを呼び出そうとするとコンパイルエラーが発生し、「実引数が多すぎます」というメッセージが表示されます。
回答を見る
  • ベストアンサー

DLLをGetProcAddress()で実行できない。

dllの操作の練習をしております。以下のソースのどこがおかしいのでしょうか? add.dllの内容は単にa+bの結果をメッセージボックスに表示させるだけの処理です。add.lib(インポートライブラリ)をリンクさせればうまく動きます。 しかし、GetProcAddress()を使って明示的にdllを呼び出そうとすると、コンパイルエラーで ADD(hWnd,5,5); の行に 「int (__stdcall *)(void)' : 実引数が多すぎます。」 となります。このメッセージの意味もわかりません。 以下のソースのどこがおかしいのでしょうか?コンパイラはVC++6.0でOSはWin2000です。 #include<windows.h> void CALLBACK ADD(HWND hwnd,int a, int b); //ウィンドウプロージャ(ここは別に普通) LRESULT CALLBACK WndProc(HWND hWnd , UINT msg , WPARAM wp , LPARAM lp) { switch (msg) { case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd , msg , wp , lp); } int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance , PSTR lpCmdLine , int nCmdShow) { static FARPROC ADD;  //あやしい HWND hWnd; MSG msg; WNDCLASS winc;     //ウィンドウを作る処理 //~(省略)~ /****明示的にdllを呼び出す****/ ADD = GetProcAddress( LoadLibrary(TEXT("add.dll")) , TEXT("ADD")); ADD(hWnd,5,5); /****************************/ while (GetMessage(&msg , NULL , 0 , 0 )) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } お願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • HogePiyo
  • ベストアンサー率57% (24/42)
回答No.1

FARPROC は恐らく int (__stdcall *)(void) と定義されていて引数を受け取らず int を戻り値として返す関数へのポインタを意味しているのでしょう。 関数 ADD のプロトタイプでは、 void CALLBACK ADD(HWND hwnd,int a, int b); と宣言されていますから、この関数のポインタを受けとって使用するには関数のポインタを受け取る変数を FARPROC にするのではなく、 void ( *func )( HWND, int, int ); というふうに宣言して、 func = GetProcAddress( LoadLibrary( TEXT( "add.dll" ) ) , TEXT( "ADD" ) ); func( hWnd, 5, 5 ); と、使用してやれば上手くいくと思います。 また、引数に HWND と int と int を取り、戻り値を返さない関数へのポインタ変数の宣言は冗長になるので以下のように宣言することも出来ます。 typedef void ( *DLLFUNC )( HWND, int, int ); DLLFUNC func; func = GetProcAddress( LoadLibrary( TEXT( "add.dll" ) ) , TEXT( "ADD" ) ); func( hWnd, 5, 5 ); 関数のポインタについては検索エンジンなどで調べてみてください。 以下、例です。 #include <stdio.h> typedef void ( *FUNC )( int, int ); void func( int hoge, int piyo ){ printf( "%d, %d", hoge, piyo ); } int main(void){ FUNC fn; fn = func; fn( 23, 43 ); return 0; }

参考URL:
http://usr_vogel.tripod.co.jp/
jimihenn
質問者

お礼

返信送れてすいません。 ありがとうございました。 おかげでうまくいきました。

関連するQ&A

  • 何もしないメッセージだけ表示するウィンドウ

    ゲーム用に何もしないメッセージだけ表示するウィンドウを作りたいのですが、 猫でもわかるゲームプログラミングのコードが間違っているのか、 機能しません。 #include <windows.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp); int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { return (int)msg.wParam; } LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { switch (msg){ } return 0; } このように、打ち込んだのですが、どこが間違っているのか解りません。 回答お願いいたします。

  • msgが定義されていない

    Visual Studio2019でwindowsアプリケーションでゲームを作っているんですが、 どうやってもmsgが定義されていないが直りません。 #include <windows.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp); //WinMain関数 int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { //ウィンドウクラスの登録 //メインウィンドウの生成 //メッセージループ return (int)msg.wParam; } //ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { //メッセージごとにやりたいことを記述する } return 0; } ご教示お願いします。

  • windowプログラム ARC C++

    今、windowプログラムで フォームの中に「エディットボックス」と「スタティックテキスト」の2つがあります。 内、スタティックテキスト内にARCで円を描き、表示したいのですがどのようにすればよいのでしょうか? 以上のことに悩んでおります。 某サイトで LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) { HDC hdc; PAINTSTRUCT ps; switch (msg) { case WM_DESTROY: PostQuitMessage(0); return 0; case WM_PAINT: hdc = BeginPaint(hwnd , &ps); Arc(hdc , 10 , 10 , 200 , 200 , 0 , 100 , 0, 100); EndPaint(hwnd , &ps); return 0; } return DefWindowProc(hwnd , msg , wp , lp); } int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance , PSTR lpCmdLine , int nCmdShow ) { HWND hwnd; MSG msg; WNDCLASS winc; winc.style = CS_HREDRAW | CS_VREDRAW; winc.lpfnWndProc = WndProc; winc.cbClsExtra = winc.cbWndExtra = 0; winc.hInstance = hInstance; winc.hIcon = LoadIcon(NULL , IDI_APPLICATION); winc.hCursor = LoadCursor(NULL , IDC_ARROW); winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); winc.lpszMenuName = NULL; winc.lpszClassName = TEXT("-"); if (!RegisterClass(&winc)) return -1; hwnd = CreateWindow(      TEXT("-") , TEXT("-") , WS_OVERLAPPEDWINDOW | WS_VISIBLE , CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT ,      NULL , NULL , hInstance , NULL); if (hwnd == NULL) return -1; while(GetMessage(&msg , NULL , 0 , 0)) DispatchMessage(&msg); return msg.wParam; } をコピペしたのですが、スタティックテキスト内表示がわからなく梃子摺っております。 ご存知の方は回答・アドバイスのほどよろしくお願いいたします。

  • ダイアログ表示後に1回だけ実行

    ダイアログベースのプログラムで、ダイアログを表示後にメッセージボックスを表示しようとして、下のプログラムのようにしたのですがダイアログが表示される前にメッセージボックスが表示されてしまいます。 ダイアログが表示された直後に1回だけ表示されるようにするにはどうすればいいですか? #include<Windows.h> #include "resource.h" HINSTANCE hinst; INT_PTR CALLBACK dlgproc(HWND,UINT,WPARAM,LPARAM); int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) { hinst=hInstance; DialogBox(hinst,TEXT("mydlgmain"),NULL,dlgproc); } INT_PTR CALLBACK dlgproc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp) { TCHAR moji[]=TEXT("ダイアログ表示"); switch(msg) { case WM_INITDIALOG: MessageBox(hwnd,moji,TEXT(""),MB_OK); return(INT_PTR)TRUE; case WM_CLOSE: EndDialog(hwnd,LOWORD(wp)); return (INT_PTR)TRUE; } return(INT_PTR)FALSE; } --- 実行環境 --- Microsoft Visual C++ 2010 Express WIN32 ユニコードビルド C言語

  • 作成プログラムを常にアクティブにしたい

    Visual C++2008 を使用して、マウスカーソルの移動及びクリックを行うプログラムを作成しています。 上記動作を行うことはできるようになったのですが、画面上のアイコンや別ウィンドウをクリックすると、作成したプログラムは非アクティブ状態になってしまいます。 そこで、ポップアップのように、作成したプログラムを常にアクティブにしようと探したところ、WM_ACTIVATEやSetForegroundWindowを使用する方法があることがわかりました。 しかし、わかっただけで、上手くポップアップするようにできずにほとほと参っております。 どなたか、C及びWindowsAPIに詳しい方で、手法がわかる方がいらっしゃったらご鞭撻のほどよろしくお願いします。 なお、現時点でのプログラムは以下のようになっております。 #include <windows.h> #include <Winuser.h> LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) { POINT p; switch (msg) { case WM_DESTROY: PostQuitMessage(0); return 0; case WM_KEYDOWN: GetCursorPos(&p); if(wp == VK_UP) p.y-=5;//矢印上が押された if(wp == VK_DOWN) p.y+=5;//矢印下が押された if(wp == VK_LEFT) p.x-=5;//矢印左が押された if(wp == VK_RIGHT) p.x+=5;//矢印右が押された if(wp == VK_RETURN){//左クリック INPUT input[] = { {INPUT_MOUSE, p.x, p.y, 0, MOUSEEVENTF_LEFTDOWN, 0, 0, }, {INPUT_MOUSE, p.x, p.y, 0, MOUSEEVENTF_LEFTUP, 0, 0, }, }; ::SendInput(2, input, sizeof(INPUT)); } SetCursorPos(p.x , p.y); return 0; } return DefWindowProc(hwnd , msg , wp , lp); } int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,PSTR lpCmdLine , int nCmdShow ) { HWND hwnd; MSG msg; WNDCLASS winc; winc.style = CS_HREDRAW | CS_VREDRAW; winc.lpfnWndProc = WndProc; winc.cbClsExtra = winc.cbWndExtra = 0; winc.hInstance = hInstance; winc.hIcon = LoadIcon(NULL , IDI_APPLICATION); winc.hCursor = LoadCursor(NULL , IDC_ARROW); winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); winc.lpszMenuName = NULL; winc.lpszClassName = TEXT("sample"); if (!RegisterClass(&winc)) return -1; hwnd = CreateWindow( TEXT("sample") , TEXT("sample") , WS_OVERLAPPEDWINDOW | WS_VISIBLE , CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT , NULL , NULL , hInstance , NULL ); SetForegroundWindow(hwnd); if (hwnd == NULL) return -1; while(GetMessage(&msg , NULL , 0 , 0)) DispatchMessage(&msg); return msg.wParam; }

  • bcc32 GetProcAddress( )

    mydll.cpp と mymain.cpp でDLL内の関数を使うテストを しようとしたところです。 GetProcAddress( ) が失敗します。 どこを直せばいいか教えてください。 ///////// mydll.cpp #include <windows.h> extern "C" __declspec(dllexport) int MyFunc(int, int); int MyFunc(int a, int b){return( a + b );} ///////// mymain.cpp #include <windows.h> typedef int (*FUNCTYPE)(int, int); LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){  HMODULE hModule;  FUNCTYPE ft;  int i;  switch(msg){  case WM_RBUTTONDOWN:   hModule = LoadLibrary("mydll.dll");   ft = (FUNCTYPE)GetProcAddress(hModule, "MyFunc");   if(ft == NULL){    //GetLastError();   }   i = (*ft)(7, 8);  break;  case WM_DESTROY:   PostQuitMessage(0);  break;  default:   return DefWindowProc(hWnd, msg, wParam, lParam);  }  return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int){  ・・・ } ///////// コンパイル C:\bcc32 -WD mydll C:\bcc32 -W mymain mydll.obj ///////// 実行 LoadLibrary( ) は NULL 以外を返しました。 DLL_PROCESS_ATTACH は確認できました。 GetProcAddress( ) は NULL を返しました。

  • デスクトップをサブクラス

    デスクトップ以外のサブクラスなら何度もやったことがあります。 DLLを使わずにデスクトップをサブクラスにできますか? DLLを使わずにデスクトップをサブクラス化しようとしたけど、 サブクラスの対象がデスクトップだと特殊なのか、 サブクラスにできていないみたいでした。 MessageBeep(0xFFFFFFFF); が実行されなかったからそう思いました。 FARPROC Org_Proc; LRESULT CALLBACK DeskProc(HWND, UINT, WPARAM, LPARAM); OrgProc = (FARPROC)GetWindowLong(HWND_DESKTOP, GWL_WNDPROC); SetWindowLong(HWND_DESKTOP, GWL_WNDPROC, (LONG)DeskProc); LRESULT CALLBACK DeskProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {  if(msg == WM_LBUTTONDOWN)MessageBeep(0xFFFFFFFF);  return CallWindowProc((WNDPROC)Org_Proc, hWnd, msg, wp, lp); }

  • BCCのコンソールアプリからウィンドウ表示

    BCCのコンソールアプリからウィンドウを表示したいのですが、うまくいきません。 なにが悪いのでしょうか・・・ どなたかお教えいただけると助かります。 よろしくお願いいたします。 コンパイラ: Borland C++ 5.5.1 bcc32 コンパイル方法: bcc32 -WC WindowTest.cpp (コンソールアプリにしているのは、標準入力を受け標準出力に出すフィルタ機能も持たせようと思っているからです。) *** ソース (WindowTest.cpp) *** #include <windows.h> LRESULT CALLBACK WndProc ( HWND hWnd, UINT msg, WPARAM wp, LPARAM lp ){ // とりあえず空 (void)hWnd; (void)msg; (void)wp; (void)lp; return 0; } int main (int argc, char**argv){ HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL); WNDCLASSEX wc; char className[] = "hoge"; memset( &wc, 0, sizeof( wc )); wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ); wc.hCursor = LoadCursor( NULL, IDC_ARROW ); wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH ); wc.lpszMenuName = NULL; wc.lpszClassName = className; wc.hIconSm = NULL; if(! RegisterClassEx( &wc )) return 1; HWND hWnd = CreateWindow(className, "Title", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, hInstance, NULL); // ← ここで失敗し、ウィンドウが表示されない if (!hWnd) return 2; ShowWindow(hWnd, NULL); UpdateWindow(hWnd); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } (void)argc; (void)argv; return 0; }

  • DragQueryFile()でエラー

    現在、VC++2005SP1でダイアログベースのアプリを書いていますが、エディットコントールでのドラッグアンドドロップの実装で躓いています。なぜかDragQueryFile()で-1が返って来て直後にGetlastError()を呼ぶと6(無効なハンドル)が返って来ます。 現象の再現を確認しながらコードを以下のレベルまで簡略にしました。 どこかまずいところがあればご教示頂きたく思います。 #include "stdafx.h" #include <stdio.h> #include <locale.h> #include <shellapi.h> #include "Resource.h" TCHAR input_file[MAX_PATH]; void InitDialog( HWND hWnd ); LRESULT CALLBACK MyDragDropProc( HWND, unsigned, WORD, LONG ); WNDPROC lpfnOldEditProc; LRESULT CALLBACK DlgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp); int APIENTRY _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpCmdLine, int nCmdShow ) {   _tsetlocale(LC_ALL, _T(""));   INT_PTR dret = DialogBox(hInst, MAKEINTRESOURCE( IDD_DIALOG ), NULL, (DLGPROC)DlgProc );   return 0; } LRESULT CALLBACK DlgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {   switch (msg) {   case WM_INITDIALOG: InitDialog( hWnd ); return TRUE;   case WM_COMMAND:     switch (LOWORD(wp)) {     case IDOK: EndDialog(hWnd, IDOK); return TRUE;     case IDCANCEL: EndDialog(hWnd, IDCANCEL); return TRUE;     }   }   return FALSE; } void InitDialog( HWND hWnd ) {   DragAcceptFiles( GetDlgItem( hWnd, IDC_EDIT_INPUT_FILE ), TRUE );   lpfnOldEditProc = (WNDPROC)SetWindowLong( GetDlgItem( hWnd, IDC_EDIT_INPUT_FILE ), GWL_WNDPROC, (LONG)MyDragDropProc ); } LRESULT CALLBACK MyDragDropProc( HWND hWnd, unsigned msg, WORD wp, LONG lp ) {   UINT wFilesDropped;   HDROP hDrop = (HDROP)wp;   TCHAR buff[256];   int err;   switch ( msg ) {   case WM_DROPFILES:     wFilesDropped = DragQueryFile( hDrop, (UINT)-1, NULL, 0 );     err = GetLastError();     _itot_s( err, buff, 256, 10 );     MessageBox( NULL, buff, NULL, MB_OK );     wFilesDropped = DragQueryFile( (HDROP)wp, 0, input_file, MAX_PATH );     MessageBox( hWnd, input_file, NULL, MB_OK );     DragFinish( hDrop );     break;   default:     return CallWindowProc( (WNDPROC)lpfnOldEditProc, hWnd, msg, wp, lp );   }   return 0; }

  • C++で質問です。

    今、キーボード操作でマウスの機能を実現しようと考えています。 現段階ではキーボードの矢印キーでマウスポインタが動くところまではできました。 これに、ENTERを押したら左クリックするように実装したいのですがどうすればよいでしょうか? いろいろ調べたのですが見つかりませんでした・・・ #include <windows.h> LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) { HDC hdc; POINT po; switch (msg) { case WM_DESTROY: PostQuitMessage(0); return 0; case WM_KEYDOWN: GetCursorPos(&po); if(wp == VK_UP) po.y-=7; if(wp == VK_DOWN) po.y+=7; if(wp == VK_LEFT) po.x-=7; if(wp == VK_RIGHT) po.x+=7; SetCursorPos(po.x , po.y); return 0; } return DefWindowProc(hwnd , msg , wp , lp); } int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance , PSTR lpCmdLine , int nCmdShow ) { HWND hwnd; MSG msg; WNDCLASS winc; winc.style = CS_HREDRAW | CS_VREDRAW; winc.lpfnWndProc = WndProc; winc.cbClsExtra = winc.cbWndExtra = 0; winc.hInstance = hInstance; winc.hIcon = LoadIcon(NULL , IDI_APPLICATION); winc.hCursor = LoadCursor(NULL , IDC_ARROW); winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); winc.lpszMenuName = NULL; winc.lpszClassName = TEXT("KITTY"); if (!RegisterClass(&winc)) return -1; hwnd = CreateWindow( TEXT("KITTY") , TEXT("Kitty on your lap") , WS_OVERLAPPEDWINDOW | WS_VISIBLE , CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT , NULL , NULL , hInstance , NULL ); if (hwnd == NULL) return -1; while(GetMessage(&msg , NULL , 0 , 0)) DispatchMessage(&msg); return msg.wParam; } これにクリック実装のプログラムを付け加えていただけると嬉しいです。

専門家に質問してみよう