/////////////////////////////////////////////下面是使用此dll調用引擎的實例代碼
CDllFunctionCall DllCall;
/*CHAR szTest1[]="Hello";
CHAR szTest2[]="Hello, World!";
std::vector<CDllVariable> Args;
Args.push_back(CDllVariable(long(0)));
Args.push_back(CDllVariable("Hello, World!"));
Args.push_back(CDllVariable("Hello!"));
Args.push_back(CDllVariable(MB_ICONINFORMATION | MB_YESNO));
INT iRetB=DllCall.Load("user32.dll","MessageBoxA");
if(FAILED(iRetB))
{
? AfxMessageBox("找不到相應函數入口");
? return ;
}
if(IDYES==(int)DllCall.Invoke(Args,CDllVariable::atInt).Data.IntVal)
{
? AfxMessageBox("檢測到確定按鈕");
}
else
{
? AfxMessageBox("檢測到取消按鈕");
}
DllCall.UnLoad();*/
DllCall.Load("Kernel32.dll","DeleteFileA");
std::vector<CDllVariable> Argss;
Argss.push_back("c:\\dd.txt");
BOOL bRet=DllCall.Invoke(Argss,CDllVariable::atInt).Data.IntVal;
if(bRet)
{
? AfxMessageBox("刪除成功");
}
else
{
? AfxMessageBox("刪除失敗");
}
///////////////////////////////////////////下面是此類的頭文件
#include <vector>class CDllVariable
{
public:
enum CDllVariableType
{
? atBool,
? atVoid,
? atInt,
? atChar,
? atWChar,
? atDouble,
? atFloat,
? atInt64
};
CDllVariableType Type;
union
{
? bool BoolVal;
? INT IntVal;
? CHAR CharVal;
? wchar_t WCharVal;
? DOUBLE DoubleVal;
? FLOAT FloatVal;
? __int64 Int64Val;
} Data;
CDllVariable();
CDllVariable(bool val);
CDllVariable(INT val);
CDllVariable(__int64 val);
CDllVariable(LONG val);
CDllVariable(FLOAT val);
CDllVariable(DOUBLE val);
CDllVariable(CHAR val);
CDllVariable(wchar_t val);
CDllVariable(LPCTSTR val);
CDllVariable(VOID * val);
};
class CDllFunctionCall??
{
public:
enum CallConvention
{
? ccStdCall,
? ccCdecl
};
public:
HRESULT Load(LPCSTR szDllPath,LPCTSTR szFuncName);
VOID UnLoad();
CDllVariable Invoke(std::vector<CDllVariable>& Args, CDllVariable::CDllVariableType ReturnType, CallConvention conv = ccStdCall);
private:
FARPROC FFuncPtr;
HMODULE m_hDllHandle;
public:
CDllFunctionCall();
virtual ~CDllFunctionCall();
};
///////////////////////////////////////////////////////下面是具體代碼的實現
CDllFunctionCall::CDllFunctionCall()
{
}
CDllFunctionCall::~CDllFunctionCall()
{
}
CDllVariable::CDllVariable(bool val)
{
Type=atBool;
Data.BoolVal=val;
}
CDllVariable::CDllVariable( INT val )
{
Type = atInt;
Data.IntVal = val;
}
CDllVariable::CDllVariable(LONG val)
{
CDllVariable(__int64(val));
}
CDllVariable::CDllVariable(VOID * val)
{
CDllVariable(INT(val));
}
CDllVariable::CDllVariable()
{
Type = atVoid;
Data.IntVal = 0;
}
CDllVariable::CDllVariable( FLOAT val )
{
Type = atFloat;
Data.FloatVal = val;
}
CDllVariable::CDllVariable( DOUBLE val )
{
Type = atDouble;
Data.DoubleVal = val;
}
CDllVariable::CDllVariable( __int64 val )
{
Type = atInt64;
Data.Int64Val = val;
}
CDllVariable::CDllVariable( wchar_t val )
{
Type = atWChar;
Data.WCharVal = val;
}
CDllVariable::CDllVariable( CHAR val )
{
Type = atChar;
Data.CharVal = val;
}
//字符串用于傳送地址進去
CDllVariable::CDllVariable(LPCTSTR val )
{
Type = atInt;
Data.IntVal =(INT)val;
}
HRESULT CDllFunctionCall::Load(LPCSTR szDllPath,LPCTSTR szFuncName)
{
m_hDllHandle=LoadLibrary(szDllPath);
if(!m_hDllHandle || m_hDllHandle==INVALID_HANDLE_VALUE)return -1;
FFuncPtr = GetProcAddress(m_hDllHandle,szFuncName);
if(!FFuncPtr)return -2;
return 0;
}
VOID CDllFunctionCall::UnLoad()
{
if(!FFuncPtr)FFuncPtr=NULL;
if(m_hDllHandle && m_hDllHandle!=INVALID_HANDLE_VALUE)
{
? FreeLibrary(m_hDllHandle);
? //CloseHandle(m_hDllHandle);
? m_hDllHandle=NULL;
}
}
CDllVariable CDllFunctionCall::Invoke(std::vector<CDllVariable>& Args, CDllVariable::CDllVariableType ReturnType, CallConvention conv )
{
if((!m_hDllHandle || m_hDllHandle==INVALID_HANDLE_VALUE) || (!FFuncPtr)) return CDllVariable(0);
??
// 用于存放8字節數據的結構
union LongType
{
? double DoubleVal;
? __int64 IntVal;
? struct??
? {
?? int Head,Tail;
? } Parts;
};
// 使用stdcall/cdecl函數調用約定,參數從右至左壓棧
for (int i=Args.size()-1; i>=0; i--)
{
? CDllVariable var = Args;
? LongType l;
? // 將單字節數據放在4字節變量中,以便入棧
? int tmp = var.Data.CharVal;
? // 將不同類型的數據壓入堆棧
? switch(Args.Type)
? {
? case CDllVariable::atBool:
?? {
??? _asm push var.Data.BoolVal
?? }
?? break;
? case CDllVariable::atChar:? // 單字節整數
?? __asm
?? {
??? push tmp
?? };
?? break;
? case CDllVariable::atDouble: // 8字節浮點
?? // 8字節數據分兩部分壓入堆棧,低位先入棧
?? l.DoubleVal = var.Data.DoubleVal;
?? __asm
?? {
??? push l.Parts.Tail
??? push l.Parts.Head
?? }
?? break;
? case CDllVariable::atFloat: // 4字節浮點
?? __asm
?? {
??? push var.Data.FloatVal;
?? }
?? break;
? case CDllVariable::atInt: // 32位整數
?? __asm push var.Data.IntVal;
?? break;
? case CDllVariable::atWChar: // 16位整數
?? __asm push var.Data.WCharVal;
?? break;
? case CDllVariable::atInt64: // 64位整數
?? l.IntVal = var.Data.Int64Val;
?? __asm
?? {
??? push l.Parts.Tail
??? push l.Parts.Head
?? }
?? break;
? case CDllVariable::atVoid: // 對于函數參數,void類型是非法的
? // throw gxException(gxString(L"Cannot pass void as an argument. (gxDllFunction::Invoke)"),__FILE__,__LINE__);
?? break;
? }
}
// 嵌入式匯編只能訪問函數內部變量,故將函數指針復制一份
FARPROC fptr = FFuncPtr;
// 調用函數,并獲得保存在EDX,EAX中的整型函數返回值
LongType ltVal;
int itval, ihval;
__asm
{
? call fptr
? mov int ptr[ihval], EDX
? mov int ptr[itval], EAX
}
ltVal.Parts.Head = ihval; // 高位字只為int64類型所使用
ltVal.Parts.Tail = itval;
// 將函數返回值整理到gxDllVaraiable結構中
CDllVariable retval;
retval.Type = ReturnType;
switch (ReturnType)
{
case CDllVariable::atChar:
? retval.Data.CharVal = ltVal.Parts.Tail;
? break;
case CDllVariable::atDouble:
? // 對于浮點類型返回值,需從FPU堆棧的棧頂中讀取
? __asm fstp [retval.Data.DoubleVal];
? break;
case CDllVariable::atFloat:
? // 對于浮點類型返回值,需從FPU堆棧的棧頂中讀取
? __asm fstp [retval.Data.FloatVal];
? break;
case CDllVariable::atInt:
? retval.Data.IntVal = ltVal.Parts.Tail;
? break;
case CDllVariable::atWChar:
? retval.Data.WCharVal = ltVal.Parts.Tail;
? break;
case CDllVariable::atInt64:
? retval.Data.Int64Val = ltVal.IntVal;
? break;
case CDllVariable::atVoid:
? break;
}
// 使用C/C++默認調用約定,需要由調用者彈出變量
if (conv == ccCdecl)
{
? for (int i=0; i<Args.size(); i++)
? {
?? if (Args.Type == CDllVariable::atDouble || Args.Type == CDllVariable::atInt64)
?? __asm
?? {
??? pop EAX
??? pop EAX
?? }
?? else
?? __asm
?? {
??? pop EAX
?? }
? }
}
return retval;
}
說明:在系統中加入這個接口,基本上等于實現了什么東西都可以調用別人的程序,不必自己實現,根據業務的多變情況
???? 隨時調用相應的功能DLL即可實現,做為程序員的明確目標:寫最少的程序!