Zugriffsverletzung-Ausnahme bei Verwendung einer DLL-Funktion
Habe ich eine einfache DLL, die als Teil meiner C++ - übungen, aber ich bin immer eine access violation exception beim Aufruf von DLL-Funktion. Hier ist die DLL-header-Datei(ich bezweifle, dass der CPP wird nützlich sein hier):
#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);
};
}
Und hier ist mein main:
#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;
}
Irgendwelche Vorschläge? Danke!
- Ist die DLL im gleichen Ordner, wo dein main-Programm ausgeführt wird?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dein problem liegt hier:
Wenn
lpfnGetProcessId
hat eine Adresse, man wirft eine exception. Wenn nicht, wird Sie später versuchen, es zu nennen (boom!).Sind Sie gehen zu wollen, um schmücken Sie Ihre Funktionen mit
extern "C"
um sicherzustellen, dass Sie exportiert werden als benutzerfreundliche Namen. Das bedeutet, Sie können nicht in einer Klasse:Ohne den code der DLL, kann man nur spekulieren, und die Benennung, die Sie gewählt haben, zu ändern scheint mid-stream, aber es sieht aus wie Sie tun, die folgenden:
1) laden Sie die dll, und eine Ausnahme werfen, wenn dieser ausfällt... ok.
2) suchen Sie eine Funktion in die dll scheint das hinzufügen von zwei Werten zusammen-aber Sie werfen eine Ausnahme, wenn dies gelingt? Da bist du nicht eine Ausnahme zu werfen, wird NULL zurückgegeben wurde und somit konnte Sie nicht zum Auffinden der Funktion.
3) Aufruf der Funktion-das ist bei NULL, und so sind Sie gehen, um hier Versagen.
Ich vermute, das problem ist, dass Sie nicht die Rechnungslegung für C++ name mangling. Sie können entweder ändern Sie den Namen der Funktion in Ihrem Aufruf von GetProcAddress (), um ein Konto für Sie richtig, oder Sie können erklären, die Funktion mit
extern "C"
zu entfernen mangeln.Sind Sie sicher, dass die Methode
MathFuncs::MyMathFuncs::Add()
ist tatsächlich exportiert als einfache "Hinzufügen", wie in IhremGetProcAddress
nennen?Ich vermute, es ist irgendeine form von C++ - Namen mangeln beteiligt.
Den Sie verwenden möchten, können DUMPBIN /EXPORTS von der Befehlszeile aus, um die tatsächlichen exportierte Methode name.
Außerdem, wenn der return-Wert von
GetProcAddress
ist nichtNULL
(sieheif
- test), ist die Funktion erfolgreich ist: warum tun Siethrow
?Beachten Sie auch, dass Ihre DLL-würde einfacher sein, wenn Sie passen Sie Ihrer Klasse header-Datei in einer Weise verwenden, Exporte und Importe, z.B.
In dieser Weise kann der client nur
#include
Ihre header-Datei (und der link mit der entsprechenden .lib-Datei), ohne VerwendungLoadLibrary
/GetProcAddress
.Ich denke Zugriffsverletzung-Ausnahme bei Verwendung einer DLL-Funktion ist die korrekte Antwort, aber es ist ziemlich schwer zu interpretieren - die Probleme, die ich sehe sind:
Die Prüfungen sind nach hinten - wenn wir nicht bekommen, eine Funktion Zeiger, wir weitergehen, und wir nur werfen, wenn wir erfolgreich einen Funktionszeiger.
Den member-Funktionen exportiert werden sollen in Ordnung, da die Funktionen statisch sind, aber wir nicht bekommen, einen Funktionszeiger, da die DLL nicht exportiert eine Funktion namens "Add" - der eigentliche name wird verstümmelt und können gefunden werden in der .map-Datei, wenn Sie erzeugt.
Da wir nicht finden, eine Funktion Zeiger, wir sind dann casting der Wert NULL an die Funktion Zeiger Typ und versuchen, es zu nennen, also das ist, wo bekommen wir unsere Zugriffsverletzung.
Sollte der code sein: