1. ホーム
  2. c++

[解決済み] DLLから関数を動的にロードする

2022-12-24 23:33:29

質問

私は .dll ファイルを少し見ていて、その使い方を理解しています。

私は funci() という名前の整数を返す関数を含む .dll ファイルを作成しました。

このコードを使用して、私は(と思う)私はプロジェクトに.dll ファイルをインポートしました(不満はありません)。

#include <windows.h>
#include <iostream>

int main() {
  HINSTANCE hGetProcIDDLL = LoadLibrary("C:\\Documents and Settings\\User\\Desktop  \\fgfdg\\dgdg\\test.dll");

  if (hGetProcIDDLL == NULL) {
    std::cout << "cannot locate the .dll file" << std::endl;
  } else {
    std::cout << "it has been called" << std::endl;
    return -1;
  }

  int a = funci();

  return a;
}

# funci function 

int funci() {
  return 40;
}

しかし、.dll をインポートしたと思われるこの .cpp ファイルをコンパイルしようとすると、次のようなエラーが発生します。

C:\Documents and Settings\User\Desktop\fgfdg\onemore.cpp||In function 'int main()':|
C:\Documents and Settings\User\Desktop\fgfdg\onemore.cpp|16|error: 'funci' was not     declared in this scope|
||=== Build finished: 1 errors, 0 warnings ===|

.dllはヘッダーファイルとは違うので、このような関数をインポートできないことは分かっていますが、試してみたことを示すために思いついた最善の方法です。

私の質問は、どのように私は hGetProcIDDLL ポインターを使用して、.dll 内の関数にアクセスすることができます。

この質問が意味を持ち、私がまた何か間違った木に吠えていないことを望みます。

どのように解決するのですか?

LoadLibrary は、あなたが考えているようなことはしません。これは DLL を現在のプロセスのメモリにロードしますが、その際に ではなく で定義された関数を魔法のようにインポートすることはありません! 関数呼び出しはコンパイル時にリンカによって解決されるため、これは不可能です。 LoadLibrary は実行時に呼び出されるからです(C++は 静的型付け 言語であることを忘れないでください)。

動的にロードされた関数のアドレスを取得するために、別のWinAPI関数が必要です。 GetProcAddress .

#include <windows.h>
#include <iostream>

/* Define a function pointer for our imported
 * function.
 * This reads as "introduce the new type f_funci as the type: 
 *                pointer to a function returning an int and 
 *                taking no arguments.
 *
 * Make sure to use matching calling convention (__cdecl, __stdcall, ...)
 * with the exported function. __stdcall is the convention used by the WinAPI
 */
typedef int (__stdcall *f_funci)();

int main()
{
  HINSTANCE hGetProcIDDLL = LoadLibrary("C:\\Documents and Settings\\User\\Desktop\\test.dll");

  if (!hGetProcIDDLL) {
    std::cout << "could not load the dynamic library" << std::endl;
    return EXIT_FAILURE;
  }

  // resolve function address here
  f_funci funci = (f_funci)GetProcAddress(hGetProcIDDLL, "funci");
  if (!funci) {
    std::cout << "could not locate the function" << std::endl;
    return EXIT_FAILURE;
  }

  std::cout << "funci() returned " << funci() << std::endl;

  return EXIT_SUCCESS;
}

また エクスポート を正しくエクスポートしてください。これは、次のように行うことができます。

int __declspec(dllexport) __stdcall funci() {
   // ...
}

Lundinが指摘するように、良い習慣として ライブラリへのハンドルを解放する を解放するのがよい習慣です。これにより、他のプロセスがまだ同じ DLL へのハンドルを保持していない場合、ライブラリがアンロードされるようになります。