Accedi alla violazione sulla funzione di esecuzione dalla dll
Domanda
Ho DLL, interfaccia su C ++ per lavorare con lui. In bcb, msvc funziona bene. Voglio usare gli script Python per accedere alla funzione in questa libreria. Genera python-package usando Swig.
File setup.py
import distutils
from distutils.core import setup, Extension
setup(name = "DCM",
version = "1.3.2",
ext_modules = [Extension("_dcm", ["dcm.i"], swig_opts=["-c++","-D__stdcall"])],
y_modules = ['dcm'])
file dcm.i
%module dcm
%include <windows.i>
%{
#include <windows.h>
#include "../interface/DcmInterface.h"
#include "../interface/DcmFactory.h"
#include "../interface/DcmEnumerations.h"
%}
%include "../interface/DcmEnumerations.h"
%include "../interface/DcmInterface.h"
%include "../interface/DcmFactory.h"
esegui questi comandi (python è associato con l'estensione .py)
setup build
setup install
utilizzando questa DLL
import dcm
f = dcm.Factory() #ok
r = f.getRegistrationMessage() #ok
print "r.GetLength() ", r.GetLength() #ok
r.SetLength(0) #access violation
Nell'ultima stringa ottengo una violazione di accesso. E ho violazione di accesso su ogni funzione utilizzando i parametri di input.
DcmInterface.h (interfaccia)
class IRegistrationMessage
{
public:
...
virtual int GetLength() const = 0;
virtual void SetLength(int value) = 0;
...
};
uRegistrationMessage.cpp (implementazione in DLL)
class TRegistrationMessage : public IRegistrationMessage
{
public:
...
virtual int GetLength() const
{
return FLength;
}
virtual void SetLength(int Value)
{
FLength = Value;
FLengthExists = true;
}
...
};
Fabbrica
DcmFactory.h (usando DLL nel codice client)
class Factory
{
private:
GetRegistrationMessageFnc GetRegistration;
bool loadLibrary(const char *dllFileName = "dcmDLL.dll" )
{
...
hDLL = LoadLibrary(dllFileName);
if (!hDLL) return false;
...
GetRegistration = (GetRegistrationMessageFnc) GetProcAddress( hDLL, "getRegistration" );
...
}
public:
Factory(const char* dllFileName = "dcmDLL.dll")
{
loadLibrary(dllFileName);
}
IRegistrationMessage* getRegistrationMessage()
{
if(!GetRegistration) return 0;
return GetRegistration();
};
};
Soluzione
Trovo bug. Se si utilizza DLL, è necessario scrivere convenzioni di chiamata in una forma esplicita come questa:
class IRegistrationMessage
{
public:
...
virtual int _cdecl GetLength() const = 0;
virtual void _cdecl SetLength(int value) = 0;
...
};
Aggiungo le convenzioni di chiamata e ora funzionano tutte bene.