当我知道它是地址和参数时,我正在尝试调用一个函数。
但我不断崩溃:
现在我想知道我的代码是否正确,或者我没有源代码的主程序也不支持这样的调用?
这是我的代码:
///////////////////////////////////////////////////////
// From "amx.c", part of the PAWN language runtime:
// http://code.google.com/p/pawnscript/source/browse/trunk/amx/amx.c
ucell GetPlayerPosAddress = NULL;
cell GetPlayerPosPositionData[5] = {4*sizeof(cell),NULL,NULL,NULL,NULL};
AMX FakeAMX;
typedef cell AMX_NATIVE_CALL n_GetPlayerPos( AMX* amx, cell* params );
n_GetPlayerPos* func_GetPlayerPos = NULL;
int GetPlayerPos(int playerid,float *x,float *y,float *z)
{
GetPlayerPosPositionData[1] = playerid;
func_GetPlayerPos(&FakeAMX,GetPlayerPosPositionData);
*x = GetPlayerPosPositionData[2];
*y = GetPlayerPosPositionData[3];
*z = GetPlayerPosPositionData[4];
return 1;
}
///////////////////////////////////////////////////////
PLUGIN_EXPORT int PLUGIN_CALL AmxLoad( AMX *amx )
{
//Code from sscanf2.5, [PAWN]SSCANF Author: Y_Less
int
num,
idx;
// Operate on the raw AMX file, don't use the amx_ functions to avoid issues
// with the fact that we've not actually finished initialisation yet. Based
// VERY heavilly on code from "amx.c" in the PAWN runtime library.
AMX_HEADER *
hdr = (AMX_HEADER *)amx->base;
AMX_FUNCSTUB *
func;
num = NUMENTRIES(hdr, natives, libraries);
for (idx = 0; idx != num; ++idx)
{
func = GETENTRY(hdr, natives, idx);
if (!strcmp("GetPlayerPos", GETENTRYNAME(hdr, func)))
{
GetPlayerPosAddress = func->address;
FakeAMX.data = NULL;
FakeAMX.base = (unsigned char*)&GetPlayerPosAddress;
n_GetPlayerPos* func_GetPlayerPos = (n_GetPlayerPos*)GetPlayerPosAddress;
std::cout << "GetPlayerPos Found!" << std::endl;
break;
}
}
//end sscanf cut
return 1;
}
我想用这段代码实现的是我想调用一个 AMX 函数,但不是从 AMX 脚本调用,而是从这段代码所在的 DLL 调用。
您在我的代码中看到任何错误还是特定于 AMX 的东西?
我确实得到“找到 GetPlayerPos 地址!” 信息。
这就是我调用函数的方式:
float X;
float Y;
float Z;
GetPlayerPos(playerid,&X,&Y,&Z);
这是定义和结构:
/* calling convention for native functions */
#if !defined AMX_NATIVE_CALL
#define AMX_NATIVE_CALL
#endif
#if defined __GNUC__
#define PACKED __attribute__((packed))
#else
#define PACKED
#endif
struct tagAMX;
typedef cell (AMX_NATIVE_CALL *AMX_NATIVE)(struct tagAMX *amx, cell *params);
typedef int (AMXAPI *AMX_CALLBACK)(struct tagAMX *amx, cell index,
cell *result, cell *params);
typedef int (AMXAPI *AMX_DEBUG)(struct tagAMX *amx);
/* The AMX structure is the internal structure for many functions. Not all
* fields are valid at all times; many fields are cached in local variables.
*/
typedef struct tagAMX {
unsigned char _FAR *base PACKED; /* points to the AMX header plus the code, optionally also the data */
unsigned char _FAR *data PACKED; /* points to separate data+stack+heap, may be NULL */
AMX_CALLBACK callback PACKED;
AMX_DEBUG debug PACKED; /* debug callback */
/* for external functions a few registers must be accessible from the outside */
cell cip PACKED; /* instruction pointer: relative to base + amxhdr->cod */
cell frm PACKED; /* stack frame base: relative to base + amxhdr->dat */
cell hea PACKED; /* top of the heap: relative to base + amxhdr->dat */
cell hlw PACKED; /* bottom of the heap: relative to base + amxhdr->dat */
cell stk PACKED; /* stack pointer: relative to base + amxhdr->dat */
cell stp PACKED; /* top of the stack: relative to base + amxhdr->dat */
int flags PACKED; /* current status, see amx_Flags() */
/* user data */
long usertags[AMX_USERNUM] PACKED;
void _FAR *userdata[AMX_USERNUM] PACKED;
/* native functions can raise an error */
int error PACKED;
/* passing parameters requires a "count" field */
int paramcount;
/* the sleep opcode needs to store the full AMX status */
cell pri PACKED;
cell alt PACKED;
cell reset_stk PACKED;
cell reset_hea PACKED;
cell sysreq_d PACKED; /* relocated address/value for the SYSREQ.D opcode */
#if defined JIT
/* support variables for the JIT */
int reloc_size PACKED; /* required temporary buffer for relocations */
long code_size PACKED; /* estimated memory footprint of the native code */
#endif
} PACKED AMX;
/* The AMX_HEADER structure is both the memory format as the file format. The
* structure is used internaly.
*/
typedef struct tagAMX_HEADER {
int32_t size PACKED; /* size of the "file" */
uint16_t magic PACKED; /* signature */
char file_version PACKED; /* file format version */
char amx_version PACKED; /* required version of the AMX */
int16_t flags PACKED;
int16_t defsize PACKED; /* size of a definition record */
int32_t cod PACKED; /* initial value of COD - code block */
int32_t dat PACKED; /* initial value of DAT - data block */
int32_t hea PACKED; /* initial value of HEA - start of the heap */
int32_t stp PACKED; /* initial value of STP - stack top */
int32_t cip PACKED; /* initial value of CIP - the instruction pointer */
int32_t publics PACKED; /* offset to the "public functions" table */
int32_t natives PACKED; /* offset to the "native functions" table */
int32_t libraries PACKED; /* offset to the table of libraries */
int32_t pubvars PACKED; /* the "public variables" table */
int32_t tags PACKED; /* the "public tagnames" table */
int32_t nametable PACKED; /* name table */
} PACKED AMX_HEADER;
#define USENAMETABLE(hdr) \
((hdr)->defsize==sizeof(AMX_FUNCSTUBNT))
#define NUMENTRIES(hdr,field,nextfield) \
(unsigned)(((hdr)->nextfield - (hdr)->field) / (hdr)->defsize)
#define GETENTRY(hdr,table,index) \
(AMX_FUNCSTUB *)((unsigned char*)(hdr) + (unsigned)(hdr)->table + (unsigned)index*(hdr)->defsize)
#define GETENTRYNAME(hdr,entry) \
(USENAMETABLE(hdr) ? \
(char *)((unsigned char*)(hdr) + (unsigned)((AMX_FUNCSTUBNT*)(entry))->nameofs) : \
((AMX_FUNCSTUB*)(entry))->name)
这就是程序中的函数“看起来像”的样子:
// native GetPlayerPos(playerid, &Float:x, &Float:y, &Float:z)
static cell AMX_NATIVE_CALL n_GetPlayerPos(AMX *amx, cell *params)
{
CHECK_PARAMS(4);
cell* cptr;
amx_GetAddr(amx, params[2], &cptr);
*cptr = amx_ftoc(pPlayer->m_vecPos.X);
amx_GetAddr(amx, params[3], &cptr);
*cptr = amx_ftoc(pPlayer->m_vecPos.Y);
amx_GetAddr(amx, params[4], &cptr);
*cptr = amx_ftoc(pPlayer->m_vecPos.Z);
return 1;
}