根據我對vc的實驗得出的結論如下:
vc對vatabled的布局是如下確定的
// This class is exported from the trydll2.dll
class __declspec(dllexport) CTrydll2 {
public:
CTrydll2(void);
virtual void diplay();
virtual int fnp(int i);
// TODO: add your methods here.
};
vtbale布局如下:
display()//第零個元素
fnp(int)//第一個元素
、。。也就是根據聲明的順序來決定他們在 vatable中的順序。
如果要在用戶端中正確使用則生民順需要一致!!!
一下是我得錯誤碼:
///////////////////////trydll2.h///////////////
#ifdef TRYDLL2_EXPORTS
#define TRYDLL2_API __declspec(dllexport)
#else
#define TRYDLL2_API __declspec(dllimport)
#endif
// This class is exported from the trydll2.dll
class TRYDLL2_API CTrydll2 {
public:
CTrydll2(void);
virtual void diplay();
virtual int fnp(int i);
// TODO: add your methods here.
};
//extern TRYDLL2_API int nTrydll2;//·ÅÔÚÕâÀï²»»áÖØ¶¨Òå!!
extern "C"
{
TRYDLL2_API int nTrydll2;
TRYDLL2_API CTrydll2 * GetInstance();
TRYDLL2_API int fnTrydll2(void);
TRYDLL2_API int fnp(int para);
};
、、、、、、、trydll2.cpp、、、、、、、、、
#include "stdafx.h"
#include "trydll2.h"
//..............................
#include <iostream>
using namespace std;
///..............................
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// This is an example of an exported variable
//TRYDLL2_API int nTrydll2=0;//½«µ¼ÖÂÖØ¶¨Òå
extern "C" TRYDLL2_API int nTrydll2=0;
// This is an example of an exported function.
TRYDLL2_API int fnTrydll2(void)
{
cout<<"fnTrydll2 /n";
return 42;
}
TRYDLL2_API CTrydll2 * GetInstance()
{
CTrydll2 *p=new CTrydll2;
return p;
}
TRYDLL2_API int fnp(int para)
{
cout<<"fnp:"<<para<<endl;
return para=1;
}
// This is the constructor of a class that has been exported.
// see trydll2.h for the class definition
CTrydll2::CTrydll2()
{
return;
}
void CTrydll2::diplay()
{
cout<<"CTrydll2::diplay"<<endl;
}
int CTrydll2::fnp(int i)
{
cout<<"CTrydll2::fnp:" <<i<<endl;
i++;
return i;
}
、、、、用戶端。。。。。。。。。。。。
#include "stdafx.h"
class __declspec(dllimport) CTrydll2
{
public:
CTrydll2(void);
virtual int fnp(int i);//請注意這裡的聲明順序和dll不一樣
virtual void diplay();
//virtual int fnp(int i);
// TODO: add your methods here.
};
//__declspec(dllimport) int nTrydll2;
//end¡£¡£¡£..
#include "windows.h"
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
HINSTANCE hi=::LoadLibrary("E://lianxi//DLL_LIB_DCOM_COM//trydll2//Debug//trydll2.dll");
if( hi == NULL )
{
cout<<"LoadLibrary error/n";
return 0;
}
//.......fn.................
FARPROC lpfn= ::GetProcAddress( hi , "fnTrydll2" );
if( lpfn == NULL )
{
cout<<"GetProcAddress fnTrydll2 error/n";
return 0;
}
lpfn();
//FARPROC == int (*lpfn)(void )
typedef int (*LPFNP)(int );
LPFNP lpfnP=(LPFNP)::GetProcAddress( hi , "fnp" );
if ( lpfnP == NULL)
{
cout<<"GetProcAddress fnp error/n";
}
else
{
lpfnP(15);
}
//......variable................
int *pi = (int *)::GetProcAddress(hi,"nTrydll2");
if( pi==NULL)
{
cout<<"cann't find nTrydll2 error/n";
//return 0;
}
//.............class........
CTrydll2 *pt = NULL;
FARPROC lpfn2 = ::GetProcAddress(hi ,"GetInstance");
if ( lpfn2 == NULL )
{
cout<<"GetProcAddress GetInstance error/n";
return 0;
}
//請注意:編譯連結沒有錯誤的
pt = (CTrydll2 *)lpfn2();
pt->diplay(); //執行時這裡實際上調用的是dll中的fnp(int )但由於參數不正確所以出現執行階段錯誤
pt->fnp(10); //執行時這裡實際上調用的是dll中的display()但由於參數不正確所以出現執行階段錯誤
/*之所以會出現上面的錯誤是由於編譯main時它確定的vtable和dll的vatble不同。編譯main時使用的是
main中聲明的 vtable,但是在運行時pt所指向的是dll的vtable所以出現了調用的錯誤
*/
::FreeLibrary( hi );
return 0;
}
//關於這一點。。。