/////////////////////////////////////////////下面是使用此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即可实现,做为程序员的明确目标:写最少的程序!