0

C ++演習の一部として単純なDLLを作成しましたが、DLL関数を呼び出すとアクセス違反の例外が発生します。これがDLLのヘッダーファイルです(CPPがここで役立つとは思えません):

#pragma once

namespace MathFuncs
{
class MyMathFuncs
{
public:
    // Returns a + b
    static __declspec(dllexport) double Add(double a, double b);

    // Returns a - b
    static __declspec(dllexport) double Subtract(double a, double b);

    // Returns a * b
    static __declspec(dllexport) double Multiply(double a, double b);

    // Returns a / b
    // Throws DivideByZeroException if b is 0
    static __declspec(dllexport) double Divide(double a, double b);
};
}

そして、これが私のメインです:

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

using namespace std;

int main(void)
{
    double (__cdecl *MYPROC)(double,double);
    /* get handle to dll */
    HINSTANCE hGetProcIDDLL = LoadLibrary("DLLExample.dll"); 
if(hGetProcIDDLL == NULL)
    throw;
   /* get pointer to the function in the dll*/
    FARPROC lpfnGetProcessID = GetProcAddress(hGetProcIDDLL,"Add"); 
    if(lpfnGetProcessID)
        throw;
    MYPROC = (double (__cdecl *)(double,double))lpfnGetProcessID;
    if(MYPROC)
        throw;

    double x = MYPROC(5.5,5);

    return 0;
}

助言がありますか?ありがとう!

4

4 に答える 4

3

あなたの問題はここにあります:

FARPROC lpfnGetProcessID = GetProcAddress(hGetProcIDDLL,"Add"); 
if(lpfnGetProcessID)  // <-- error!
    throw;
MYPROC = (double (__cdecl *)(double,double))lpfnGetProcessID;
if(MYPROC)  // <-- error!
    throw;

double x = MYPROC(5.5,5);

アドレスがある場合lpfnGetProcessIdは、例外をスローしています。そうでない場合は、後でそれを呼び出そうとします (ブーム!)。

extern "C"関数がわかりやすい名前でエクスポートされるように、関数を で装飾する必要があります。これは、クラス内に存在できないことを意味します。

namespace MathFuncs
{
   extern "C" __declspec(dllexport) double Add(double, double);
}
于 2012-09-14T16:43:05.363 に答える
2

DLL へのコードがないと、推測することしかできず、選択した命名は途中で変更されているように見えますが、次のことを行っているようです。

1)dllをロードし、これが失敗した場合は例外をスローします... OK。2) 2 つの値を加算するように見える dll 内の関数を見つけますが、これが成功すると例外がスローされますか? 例外をスローしていないため、NULL が返されたため、関数を見つけることができませんでした。3) 関数を呼び出します -- これは NULL なので、ここで失敗します。

問題は、C++ の名前マングリングを考慮していないことだと思います。GetProcAddress() への呼び出しで関数名を変更して正しく説明するか、関数を宣言してextern "C"マングリングを削除することができます。

于 2012-09-14T16:33:11.563 に答える
1

呼び出しのように、メソッドMathFuncs::MyMathFuncs::Add()が実際に単純な「追加」としてエクスポートされていることを確認していますGetProcAddressか?

なんらかの形式の C++ 名マングリングが関与していると思われます。

コマンド ラインからDUMPBIN /EXPORTSを使用して、実際にエクスポートされたメソッド名を確認することができます。

さらに、の戻り値がGetProcAddressそうでない場合 NULLifテストを参照)、関数は成功します。なぜthrowですか?

クラスヘッダーファイルをエクスポートとインポートの両方で使用するように調整すると、DLL の使用がより簡単になることにも注意してください。

#if defined(MATHFUNCS_EXPORT) // Inside DLL implementation
#define MATHFUNCS_API __declspec(dllexport)
#else   // Outside DLL
#define MATHFUNCS_API __declspec(dllimport)
#endif  // MATHFUNCS_EXPORT

class MyMathFuncs
{
public:

  static MATHFUNCS_API double Add(double a, double b);
  ...
};

このようにして、クライアントは/#includeを使用せずに、ヘッダー ファイル (および対応する .lib ファイルとリンク)のみを使用できます。LoadLibraryGetProcAddress

于 2012-09-14T16:28:48.663 に答える