예제 #1
0
int main(int argc, char* argv[])
{
  DCCallVM* vm;
  int result;
  int total;
  vm = dcNewCallVM(4096);
  dcReset(vm);

  dcArgShort(vm, 0xFFFF );
  result = dcCallInt( vm, &add1s );
  total = (result == 0x10000);
  printf("result: sign: %d\n", total); 
 
  if (!total) {
    //
    // TEST BUGFIX: use instead..
    //
    dcReset(vm);
    dcArgUShort( vm, 0xFFFF );
    result = dcCallInt( vm, &add1s );
    total = (result == 0x10000);
    printf("result: sign (bugfix): %d\n", total); 
  }
  
  // result = dcCallInt( vm, &add1s );
  // total = (result == 0x10000);
  
  // OLD TEST: updated to using 'short'
  // dcArgChar( vm, (char) 255 );
  // result = dcCallInt( vm, &add1 );
  // total = (result == 256);
  
  // printf("result: sign: %d\n", total); 
  return 0;
}
예제 #2
0
파일: api.c 프로젝트: svn2github/dyncall
SEXP r_dcMode(SEXP callvm, SEXP id)
{
  DCCallVM* pvm = R_ExternalPtrAddr(callvm);
  dcMode( pvm, INTEGER(id)[0] );
  dcReset( pvm );
  return R_NilValue;
}
예제 #3
0
void dc_callvm_mode_ppc32(DCCallVM* in_self, DCint mode)
{
    DCCallVM_ppc32* self = (DCCallVM_ppc32*) in_self;
    DCCallVM_vt* vt;
    switch(mode) {

    case DC_CALL_C_PPC32_OSX:

#if defined(DC__ABI_Darwin)
    case DC_CALL_C_DEFAULT:
    case DC_CALL_C_ELLIPSIS:
#endif

        vt = &gVT_ppc32_darwin;
        break;

    case DC_CALL_C_PPC32_SYSV:

#if defined(DC__ABI_SysV)
    case DC_CALL_C_DEFAULT:
    case DC_CALL_C_ELLIPSIS:
#endif

        vt = &gVT_ppc32_sysv;
        break;

    default:
        self->mInterface.mError = DC_ERROR_UNSUPPORTED_MODE;
        return;
    }

    dc_callvm_base_init(&self->mInterface, vt);

    dcReset(in_self);
}
예제 #4
0
int syscall_write(int fd, char* buf, size_t len)
{
  dcReset(callvm);
  dcArgInt(callvm, fd);
  dcArgPointer(callvm, buf);
  dcArgInt(callvm, len);
  return dcCallInt(callvm, (DCpointer)(ptrdiff_t)SYS_write);
}
예제 #5
0
void cleanupCallHandler(CallTempStruct* call)
{
	JNIEnv *env = call->env;
	size_t i, n;
	for (i = 0, n = call->localRefsToCleanup.length; i < n; i++) {
		(*env)->DeleteLocalRef(env, call->localRefsToCleanup.buffer[i]);
	}
	call->localRefsToCleanup.length = 0;
	dcReset(call->vm);
	releaseTempCallStruct(call->env, call);
}
예제 #6
0
float forwardCaller(void* cb, float value) {
	DCCallVM* vm = dcNewCallVM(1024);
	dcReset(vm);

	dcArgPointer(vm, NULL);
	dcArgPointer(vm, NULL);
	dcArgPointer(vm, cb);
	dcArgFloat(vm, value);
	float res = dcCallFloat(vm, forwardFloatCall);
	dcFree(vm);
	return res;
}
예제 #7
0
int main(int argc, char* argv[])
{
  DCCallVM* vm;
  DCValue ret;
  int r = 1;

  dcTest_initPlatform();

  /* allocate call vm */
  vm = dcNewCallVM(4096);


  /* calls using 'formatted' API */
  dcReset(vm);
  printf("callf iii)i:       ");
  dcCallF(vm, &ret, (void*)&vf_iii, "iii)i", 1, 2, 3);
  r = ret.i && r;

  dcReset(vm);
  printf("\ncallf ffiffiffi)i: ");
  dcCallF(vm, &ret, (void*)&vf_ffiffiffi, "ffiffiffi)i", 1.f, 2.f, 3, 4.f, 5.f, 6, 7.f, 8.f, 9);
  r = ret.i && r;


  /* arg binding then call using 'formatted' API */
  dcReset(vm);
  printf("\nargf iii)i       then call: ");
  dcArgF(vm, "iii)i", 1, 2, 3);
  r = r && dcCallInt(vm, (void*)&vf_iii);

  dcReset(vm);
  printf("\nargf iii         then call: ");
  dcArgF(vm, "iii", 1, 2, 3);
  r = r && dcCallInt(vm, (void*)&vf_iii);

  dcReset(vm);
  printf("\nargf ffiffiffi)i then call: ");
  dcArgF(vm, "ffiffiffi)i", 1.f, 2.f, 3, 4.f, 5.f, 6, 7.f, 8.f, 9);
  r = r && dcCallInt(vm, (void*)&vf_ffiffiffi);

  dcReset(vm);
  printf("\nargf ffiffiffi   then call: ");
  dcArgF(vm, "ffiffiffi", 1.f, 2.f, 3, 4.f, 5.f, 6, 7.f, 8.f, 9);
  r = r && dcCallInt(vm, (void*)&vf_ffiffiffi);


  /* free vm */
  dcFree(vm);

  printf("\nresult: callf: %d\n", r);

  dcTest_deInitPlatform();
  
  return 0;
}
예제 #8
0
파일: main.c 프로젝트: dod38fr/dyncall
int main(int argc, char* argv[])
{
  int total;

  dcTest_initPlatform();

  init_K(G_maxargs);
  G_callvm = (DCCallVM*) dcNewCallVM(4096);
  dcReset(G_callvm);
  total = run_all();
  printf("result: call_suite: %d\n", total);

  dcTest_deInitPlatform();

  return 0;
}
예제 #9
0
static void dc_callvm_mode_arm32_thumb(DCCallVM* in_self,DCint mode)
{
  DCCallVM_arm32_thumb* self = (DCCallVM_arm32_thumb*) in_self;
  DCCallVM_vt*  vt;
  switch(mode) {
/* Check OS if we need EABI as default. */
    case DC_CALL_C_ELLIPSIS:
#if defined(DC__ABI_ARM_EABI)
    case DC_CALL_C_DEFAULT:          vt = &gVT_arm32_thumb_eabi; break;
#else
    case DC_CALL_C_DEFAULT:          vt = &gVT_arm32_thumb;      break;
#endif
    case DC_CALL_C_ARM_THUMB:        vt = &gVT_arm32_thumb;      break;
    case DC_CALL_C_ARM_THUMB_EABI:   vt = &gVT_arm32_thumb_eabi; break;
    default: self->mInterface.mError = DC_ERROR_UNSUPPORTED_MODE; return;
  }
  self->mInterface.mVTpointer = vt;
  dcReset(in_self);
}
예제 #10
0
char floatCbHandler(DCCallback* pcb, DCArgs* args, DCValue* result, void* userdata) {
	dcbArgPointer(args);
	dcbArgPointer(args);
	dcbArgPointer(args);
	dcbArgInt(args);
	dcbArgInt(args);
	dcbArgFloat(args);
	float value = dcbArgFloat(args);


	{
		DCCallVM* vm = dcNewCallVM(1024);
		dcReset(vm);
		dcArgFloat(vm, value);
		float res = dcCallFloat(vm, floatIncr);
		result->f = res;
	}
	return DC_SIGCHAR_FLOAT;
}
예제 #11
0
파일: main.c 프로젝트: QAndot/dyncall
int main(int argc, char* argv[])
{
  DCCallVM* vm;
  DCValue r;

  dcTest_initPlatform();

  /* allocate call vm */
  vm = dcNewCallVM(4096);
  dcReset(vm);

  /* call using 'formatted' API */
  dcCallF(vm, &r, (void*) &vf_iii, "iii)i", 1, 2, 3);

  /* free vm */
  dcFree(vm);

  printf("result: callf: %d\n", r.i);

  dcTest_deInitPlatform();
  
  return 0;
}
예제 #12
0
// Shareable implementation for argument binding used in ArgF and CallF  below.
static void dcArgF_impl(DCCallVM* vm, const DCsigchar** sigptr, va_list args)
{
  DCsigchar ch;
  dcReset(vm);
  while((ch=*(*sigptr)++) != '\0' && ch != DC_SIGCHAR_ENDARG) {
    switch(ch) {
      case DC_SIGCHAR_BOOL:      dcArgBool    (vm, (DCbool)           va_arg(args, DCint     )); break;
      case DC_SIGCHAR_CHAR:      dcArgChar    (vm, (DCchar)           va_arg(args, DCint     )); break;
      case DC_SIGCHAR_UCHAR:     dcArgChar    (vm, (DCchar)(DCuchar)  va_arg(args, DCint     )); break;
      case DC_SIGCHAR_SHORT:     dcArgShort   (vm, (DCshort)          va_arg(args, DCint     )); break;
      case DC_SIGCHAR_USHORT:    dcArgShort   (vm, (DCshort)(DCushort)va_arg(args, DCint     )); break;
      case DC_SIGCHAR_INT:       dcArgInt     (vm, (DCint)            va_arg(args, DCint     )); break;
      case DC_SIGCHAR_UINT:      dcArgInt     (vm, (DCint)(DCuint)    va_arg(args, DCint     )); break;
      case DC_SIGCHAR_LONG:      dcArgLong    (vm, (DClong)           va_arg(args, DClong    )); break;
      case DC_SIGCHAR_ULONG:     dcArgLong    (vm, (DCulong)          va_arg(args, DClong    )); break;
      case DC_SIGCHAR_LONGLONG:  dcArgLongLong(vm, (DClonglong)       va_arg(args, DClonglong)); break;
      case DC_SIGCHAR_ULONGLONG: dcArgLongLong(vm, (DCulonglong)      va_arg(args, DClonglong)); break;
      case DC_SIGCHAR_FLOAT:     dcArgFloat   (vm, (DCfloat)          va_arg(args, DCdouble  )); break;
      case DC_SIGCHAR_DOUBLE:    dcArgDouble  (vm, (DCdouble)         va_arg(args, DCdouble  )); break;
      case DC_SIGCHAR_POINTER:   dcArgPointer (vm, (DCpointer)        va_arg(args, DCpointer )); break;
      case DC_SIGCHAR_STRING:    dcArgPointer (vm, (DCpointer)        va_arg(args, DCpointer )); break;
    }
  }
}
void cleanupCallHandler(CallTempStruct* call)
{
    dcReset(call->vm);
    releaseTempCallStruct(call->env, call);
}
예제 #14
0
파일: invoke.c 프로젝트: MoarVM/dyncall
int invoke(char const* signature, void* t)
{
  DCCallVM   * p = (DCCallVM*) G_callvm;
  char const * sig = signature;
  char         rtype;
  char         atype;
  int          pos = 0;
  int          s = 0;

  clear_V();
  
  rtype = *sig++;
  dcReset(p);

  while ( (atype = *sig++) != '\0') {
    pos++;
    switch(atype) {
      case 'c': dcArgChar    (p,K_c[pos]); break;
      case 's': dcArgShort   (p,K_s[pos]); break;
      case 'i': dcArgInt     (p,K_i[pos]); break;
      case 'j': dcArgLong    (p,K_j[pos]); break;
      case 'l': dcArgLongLong(p,K_l[pos]); break;
      case 'p': dcArgPointer (p,K_p[pos]); break;
      case 'f': dcArgFloat   (p,K_f[pos]); break;
      case 'd': dcArgDouble  (p,K_d[pos]); break;
      default: printf("unknown atype '%c' (1) ;", atype); return 0;
    }
  }
  
  switch(rtype) 
  {
    case 'v': dcCallVoid(p,t); s=1; /*TODO:check that no return-arg was touched.*/ break;
    case 'c': s = (dcCallChar    (p,t) == K_c[pos]) ; break;
    case 's': s = (dcCallShort   (p,t) == K_s[pos]) ; break;
    case 'i': s = (dcCallInt     (p,t) == K_i[pos]) ; break;
    case 'j': s = (dcCallLong    (p,t) == K_j[pos]) ; break;
    case 'l': s = (dcCallLongLong(p,t) == K_l[pos]) ; break;
    case 'p': s = (dcCallPointer (p,t) == K_p[pos]) ; break;
    case 'f': s = (dcCallFloat   (p,t) == K_f[pos]) ; break;
    case 'd': s = (dcCallDouble  (p,t) == K_d[pos]) ; break;
    default: printf("unknown rtype '%c'", rtype); return 0;
  }

  if (!s) { printf("rval wrong;"); return 0; }
  /* test: */
  sig = signature+1;
  pos = 1;
  while ( (atype = *sig++) != '\0') {
    switch(atype) {
#if 0
#define X(CH,T,QCH) case QCH: s = (V_##CH[pos] == K_##CH[pos]); break;
DEF_TYPES
#undef X
#endif
      case 'c': s = ( V_c[pos] == K_c[pos] ); if (!s) printf("'c':%d: %d != %d ; ", pos, V_c[pos], K_c[pos]); break;
      case 's': s = ( V_s[pos] == K_s[pos] ); if (!s) printf("'s':%d: %d != %d ; ", pos, V_s[pos], K_s[pos]); break;
      case 'i': s = ( V_i[pos] == K_i[pos] ); if (!s) printf("'i':%d: %d != %d ; ", pos, V_i[pos], K_i[pos]); break;
      case 'j': s = ( V_j[pos] == K_j[pos] ); if (!s) printf("'j':%d: %ld != %ld ; ", pos, V_j[pos], K_j[pos]); break;
      case 'l': s = ( V_l[pos] == K_l[pos] ); if (!s) printf("'l':%d: %lld != %lld ; ", pos, V_l[pos], K_l[pos]); break;
      case 'p': s = ( V_p[pos] == K_p[pos] ); if (!s) printf("'p':%d: %lld != %lld ; ", pos, (long long) V_p[pos], (long long) K_p[pos]); break;
      case 'f': s = ( V_f[pos] == K_f[pos] ); if (!s) printf("'f':%d: %f != %f ; ", pos, V_f[pos], K_f[pos]); break;
      case 'd': s = ( V_d[pos] == K_d[pos] ); if (!s) printf("'d':%d: %f != %f ; ", pos, V_d[pos], K_d[pos]); break;
      default: printf("unknown atype '%c' ; ", atype); return 0;
    }
    if (!s) {
      printf("arg mismatch at %d ; ", pos);
      return 0;
    }
    pos++;
  }
  return 1;
}
예제 #15
0
/* libcall(const libname[], const funcname[], const typestring[], ...)
 *
 * Loads the DLL or shared library if not yet loaded (the name comparison is
 * case sensitive).
 *
 * typestring format:
 *    Whitespace is permitted between the types, but not inside the type
 *    specification. The string "ii[4]&u16s" is equivalent to "i i[4] &u16 s",
 *    but the latter is easier on the eye.
 *
 * types:
 *    i = signed integer, 16-bit in Windows 3.x, else 32-bit in Win32 and Linux
 *    u = unsigned integer, 16-bit in Windows 3.x, else 32-bit in Win32 and Linux
 *    f = IEEE floating point, 32-bit
 *    p = packed string
 *    s = unpacked string
 *    The difference between packed and unpacked strings is only relevant when
 *    the parameter is passed by reference (see below).
 *
 * pass-by-value and pass-by-reference:
 *    By default, parameters are passed by value. To pass a parameter by
 *    reference, prefix the type letter with an "&":
 *    &i = signed integer passed by reference
 *    i = signed integer passed by value
 *    Same for '&u' versus 'u' and '&f' versus 'f'.
 *
 *    Arrays are passed by "copy & copy-back". That is, libcall() allocates a
 *    block of dynamic memory to copy the array into. On return from the foreign
 *    function, libcall() copies the array back to the abstract machine. The
 *    net effect is similar to pass by reference, but the foreign function does
 *    not work in the AMX stack directly. During the copy and the copy-back
 *    operations, libcall() may also transform the array elements, for example
 *    between 16-bit and 32-bit elements. This is done because Pawn only
 *    supports a single cell size, which may not fit the required integer size
 *    of the foreign function.
 *
 *    See "element ranges" for the syntax of passing an array.
 *
 *    Strings may either be passed by copy, or by "copy & copy-back". When the
 *    string is an output parameter (for the foreign function), the size of the
 *    array that will hold the return string must be indicated between square
 *    brackets behind the type letter (see "element ranges"). When the string
 *    is "input only", this is not needed --libcall() will determine the length
 *    of the input string itself.
 *
 *    The tokens 'p' and 's' are equivalent, but 'p[10]' and 's[10]' are not
 *    equivalent: the latter syntaxes determine whether the output from the
 *    foreign function will be stored as a packed or an unpacked string.
 *
 * element sizes:
 *    Add an integer behind the type letter; for example, 'i16' refers to a
 *    16-bit signed integer. Note that the value behind the type letter must
 *    be either 8, 16 or 32.
 *
 *    You should only use element size specifiers on the 'i' and 'u' types. That
 *    is, do not use these specifiers on 'f', 's' and 'p'.
 *
 * element ranges:
 *    For passing arrays, the size of the array may be given behind the type
 *    letter and optional element size. The token 'u[4]' indicates an array of
 *    four unsigned integers, which are typically 32-bit. The token 'i16[8]'
 *    is an array of 8 signed 16-bit integers. Arrays are always passed by
 *    "copy & copy-back"
 *
 * When compiled as Unicode, this library converts all strings to Unicode
 * strings.
 *
 * The calling convention for the foreign functions is assumed:
 * -  "__stdcall" for Win32,
 * -  "far pascal" for Win16
 * -  and the GCC default for Unix/Linux (_cdecl)
 *
 * C++ name mangling of the called function is not handled (there is no standard
 * convention for name mangling, so there is no portable way to convert C++
 * function names to mangled names). Win32 name mangling (used by default by
 * Microsoft compilers on functions declared as __stdcall) is also not handled.
 *
 * Returns the value of the called function.
 */
static cell AMX_NATIVE_CALL n_libcall(AMX *amx, const cell *params)
{
  const TCHAR *libname, *funcname, *typestring;
  MODLIST *item;
  int paramidx, typeidx, idx;
  PARAM ps[MAXPARAMS];
  cell *cptr,result;
  LIBFUNC LibFunc;

  amx_StrParam(amx, params[1], libname);
  item = findlib(&ModRoot, amx, libname);
  if (item == NULL)
    item = addlib(&ModRoot, amx, libname);
  if (item == NULL) {
    amx_RaiseError(amx, AMX_ERR_NATIVE);
    return 0;
  } /* if */

  /* library is loaded, get the function */
  amx_StrParam(amx, params[2], funcname);
  LibFunc=(LIBFUNC)SearchProcAddress(item->inst, funcname);
  if (LibFunc==NULL) {
    amx_RaiseError(amx, AMX_ERR_NATIVE);
    return 0;
  } /* if */

  #if defined HAVE_DYNCALL_H
    /* (re-)initialize the dyncall library */
    if (dcVM==NULL) {
      dcVM=dcNewCallVM(4096);
      dcMode(dcVM,DC_CALL_C_X86_WIN32_STD);
    } /* if */
    dcReset(dcVM);
  #endif

  /* decode the parameters */
  paramidx=typeidx=0;
  amx_StrParam(amx, params[3], typestring);
  while (paramidx < MAXPARAMS && typestring[typeidx]!=__T('\0')) {
    /* skip white space */
    while (typestring[typeidx]!=__T('\0') && typestring[typeidx]<=__T(' '))
      typeidx++;
    if (typestring[typeidx]==__T('\0'))
      break;
    /* save "pass-by-reference" token */
    ps[paramidx].type=0;
    if (typestring[typeidx]==__T('&')) {
      ps[paramidx].type=BYREF;
      typeidx++;
    } /* if */
    /* store type character */
    ps[paramidx].type |= (unsigned char)typestring[typeidx];
    typeidx++;
    /* set default size, then check for an explicit size */
    #if defined __WIN32__ || defined _WIN32 || defined WIN32
      ps[paramidx].size=32;
    #elif defined _Windows
      ps[paramidx].size=16;
    #endif
    if (_istdigit(typestring[typeidx])) {
      ps[paramidx].size=(unsigned char)_tcstol(&typestring[typeidx],NULL,10);
      while (_istdigit(typestring[typeidx]))
        typeidx++;
    } /* if */
    /* set default range, then check for an explicit range */
    ps[paramidx].range=1;
    if (typestring[typeidx]=='[') {
      ps[paramidx].range=_tcstol(&typestring[typeidx+1],NULL,10);
      while (typestring[typeidx]!=']' && typestring[typeidx]!='\0')
        typeidx++;
      ps[paramidx].type |= BYREF; /* arrays are always passed by reference */
      typeidx++;                  /* skip closing ']' too */
    } /* if */
    /* get pointer to parameter */
    cptr=amx_Address(amx,params[paramidx+4]);
    switch (ps[paramidx].type) {
    case 'i': /* signed integer */
    case 'u': /* unsigned integer */
    case 'f': /* floating point */
      assert(ps[paramidx].range==1);
      ps[paramidx].v.val=(int)*cptr;
      break;
    case 'i' | BYREF:
    case 'u' | BYREF:
    case 'f' | BYREF:
      ps[paramidx].v.ptr=cptr;
      if (ps[paramidx].range>1) {
        /* convert array and pass by address */
        ps[paramidx].v.ptr = fillarray(amx, &ps[paramidx], cptr);
      } /* if */
      break;
    case 'p':
    case 's':
    case 'p' | BYREF:
    case 's' | BYREF:
      if (ps[paramidx].type=='s' || ps[paramidx].type=='p') {
        int len;
        /* get length of input string */
        amx_StrLen(cptr,&len);
        len++;            /* include '\0' */
        /* check max. size */
        if (len<ps[paramidx].range)
          len=ps[paramidx].range;
        ps[paramidx].range=len;
      } /* if */
      ps[paramidx].v.ptr=malloc(ps[paramidx].range*sizeof(TCHAR));
      if (ps[paramidx].v.ptr==NULL)
        return amx_RaiseError(amx, AMX_ERR_NATIVE);
      amx_GetString((char *)ps[paramidx].v.ptr,cptr,sizeof(TCHAR)>1,UNLIMITED);
      break;
    default:
      /* invalid parameter type */
      return amx_RaiseError(amx, AMX_ERR_NATIVE);
    } /* switch */
    paramidx++;
  } /* while */
  if ((params[0]/sizeof(cell)) - 3 != (size_t)paramidx)
    return amx_RaiseError(amx, AMX_ERR_NATIVE); /* format string does not match number of parameters */

  #if defined HAVE_DYNCALL_H
    for (idx = 0; idx < paramidx; idx++) {
      if ((ps[idx].type=='i' || ps[idx].type=='u' || ps[idx].type=='f') && ps[idx].range==1) {
        switch (ps[idx].size) {
        case 8:
          dcArgChar(dcVM,(unsigned char)(ps[idx].v.val & 0xff));
          break;
        case 16:
          dcArgShort(dcVM,(unsigned short)(ps[idx].v.val & 0xffff));
          break;
        default:
          dcArgLong(dcVM,ps[idx].v.val);
        } /* switch */
      } else {
        dcArgPointer(dcVM,ps[idx].v.ptr);
      } /* if */
    } /* for */
    result=(cell)dcCallPointer(dcVM,(void*)LibFunc);
  #else /* HAVE_DYNCALL_H */
    /* push the parameters to the stack (left-to-right in 16-bit; right-to-left
     * in 32-bit)
     */
#if defined __WIN32__ || defined _WIN32 || defined WIN32
    for (idx=paramidx-1; idx>=0; idx--) {
#else
    for (idx=0; idx<paramidx; idx++) {
#endif
      if ((ps[idx].type=='i' || ps[idx].type=='u' || ps[idx].type=='f') && ps[idx].range==1) {
        switch (ps[idx].size) {
        case 8:
          push((unsigned char)(ps[idx].v.val & 0xff));
          break;
        case 16:
          push((unsigned short)(ps[idx].v.val & 0xffff));
          break;
        default:
          push(ps[idx].v.val);
        } /* switch */
      } else {
        push(ps[idx].v.ptr);
      } /* if */
    } /* for */

    /* call the function; all parameters are already pushed to the stack (the
     * function should remove the parameters from the stack)
     */
    result=LibFunc();
  #endif /* HAVE_DYNCALL_H */

  /* store return values and free allocated memory */
  for (idx=0; idx<paramidx; idx++) {
    switch (ps[idx].type) {
    case 'p':
    case 's':
      free(ps[idx].v.ptr);
      break;
    case 'p' | BYREF:
    case 's' | BYREF:
      cptr=amx_Address(amx,params[idx+4]);
      amx_SetString(cptr,(char *)ps[idx].v.ptr,ps[idx].type==('p'|BYREF),sizeof(TCHAR)>1,UNLIMITED);
      free(ps[idx].v.ptr);
      break;
    case 'i':
    case 'u':
    case 'f':
      assert(ps[idx].range==1);
      break;
    case 'i' | BYREF:
    case 'u' | BYREF:
    case 'f' | BYREF:
      cptr=amx_Address(amx,params[idx+4]);
      if (ps[idx].range==1) {
        /* modify directly in the AMX (no memory block was allocated */
        switch (ps[idx].size) {
        case 8:
          *cptr= (ps[idx].type==('i' | BYREF)) ? (long)((signed char)*cptr) : (*cptr & 0xff);
          break;
        case 16:
          *cptr= (ps[idx].type==('i' | BYREF)) ? (long)((short)*cptr) : (*cptr & 0xffff);
          break;
        } /* switch */
      } else {
        int i;
        for (i=0; i<ps[idx].range; i++) {
          switch (ps[idx].size) {
          case 8:
            *cptr= (ps[idx].type==('i' | BYREF)) ? ((signed char*)ps[idx].v.ptr)[i] : ((unsigned char*)ps[idx].v.ptr)[i];
            break;
          case 16:
            *cptr= (ps[idx].type==('i' | BYREF)) ? ((short*)ps[idx].v.ptr)[i] : ((unsigned short*)ps[idx].v.ptr)[i];
            break;
          default:
            *cptr= (ps[idx].type==('i' | BYREF)) ? ((long*)ps[idx].v.ptr)[i] : ((unsigned long*)ps[idx].v.ptr)[i];
          } /* switch */
        } /* for */
        free((char *)ps[idx].v.ptr);
      } /* if */
      break;
    default:
      assert(0);
    } /* switch */
  } /* for */

  return result;
}

/* bool: libfree(const libname[]="")
 * When the name is an empty string, this function frees all libraries (for this
 * abstract machine). The name comparison is case sensitive.
 * Returns true if one or more libraries were freed.
 */
static cell AMX_NATIVE_CALL n_libfree(AMX *amx, const cell *params)
{
  const TCHAR *libname;
  amx_StrParam(amx,params[1],libname);
  return freelib(&ModRoot,amx,libname) > 0;
}

#else /* HAVE_DYNCALL_H || WIN32_FFI */

static cell AMX_NATIVE_CALL n_libcall(AMX *amx, const cell *params)
{
  (void)amx;
  (void)params;
  return 0;
}
예제 #16
0
static PyObject*
pydc_call(PyObject* self, PyObject* in_args)
{
  PyObject*   pcobj_funcptr;
  const char* signature;
  PyObject*   args;
  int         l;
  const char* ptr;
  char        ch;
  int         pos;
  void*       pfunc;
  
  if ( !PyArg_ParseTuple(in_args,"OsO", &pcobj_funcptr, &signature, &args) ) return PyErr_Format(PyExc_RuntimeError, "argument mismatch");
  pfunc = PyCObject_AsVoidPtr(pcobj_funcptr);  
  if ( !pfunc ) return PyErr_Format( PyExc_RuntimeError, "function pointer is NULL" );
  l = PyTuple_Size(args);

  ptr = signature;
  pos = 0; 

  dcReset(gpCall);
  
  while ( (ch = *ptr) != '\0' && ch != ')' ) 
  {
    PyObject* po;

    int index = pos+1;

    if (pos > l) return PyErr_Format( PyExc_RuntimeError, "expecting more arguments" );

    po = PyTuple_GetItem(args,pos);

    switch(ch) 
    {
      case DC_SIGCHAR_BOOL:
      {
        DCbool b;
        if ( !PyBool_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a bool", index ); 
        b = (Py_True == po) ? DC_TRUE : DC_FALSE;
        dcArgBool(gpCall, b);
      }
      break;
      case DC_SIGCHAR_CHAR:
      {
        DCchar c;
        if ( PyString_Check(po) )
        {
          // Py_ssize_t l;
          size_t l;
          char* s;
          l = PyString_GET_SIZE(po);
          if (l != 1) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a string with length of 1 (a char string)", index );          
          s = PyString_AsString(po);          
          c = (DCchar) s[0];
        }
        else if ( PyInt_Check(po) ) 
        {
          long l;
          l = PyInt_AsLong(po);
          if ( (l > CHAR_MAX) || (l < CHAR_MIN)) return PyErr_Format( PyExc_RuntimeError, "value out of range at argument %d - expecting a char code", index );
          c = (DCchar) l;
        }
        else return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a char", index );        
        dcArgChar(gpCall, c);
      }
      break;
      case DC_SIGCHAR_SHORT:
      {
        DCshort s;
        long v;
        if ( !PyInt_Check(po) )
          return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a short int", index ); 
        v = PyInt_AS_LONG(po);
        if ( (v < SHRT_MIN) || (v > SHRT_MAX) ) 
          return PyErr_Format( PyExc_RuntimeError, "value out of range at argument %d - expecting a short value", index );
        s = (DCshort) v;
        dcArgShort(gpCall, s);
      } 
      break;
      case DC_SIGCHAR_INT:
      {
        long v;
        if ( !PyInt_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting an int", index ); 
        v = PyInt_AS_LONG(po);
        dcArgInt(gpCall, (DCint) v );
      }
      break;
      case DC_SIGCHAR_LONG:
      {
        long v;
        if ( !PyInt_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting an int", index ); 
        v = PyInt_AsLong(po);
        
      }
      break;
      case DC_SIGCHAR_LONGLONG:
      {
        PY_LONG_LONG pl;
        DClonglong dl;
        if ( !PyLong_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a long long", index );
        pl = PyLong_AsLongLong(po);
        dl = (DClonglong) pl;
        dcArgLongLong(gpCall, dl );
      }
      break;
      case DC_SIGCHAR_FLOAT:
      {
        DCfloat f;
        if (!PyFloat_Check(po)) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expeecting a float", index );
        f = (float) PyFloat_AsDouble(po);
        dcArgFloat(gpCall, f);
      }
      break;
      case DC_SIGCHAR_DOUBLE:
      {
        double d;
        if (!PyFloat_Check(po)) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expeecting a float", index );
        d = PyFloat_AsDouble(po);
        dcArgDouble(gpCall, d);      
      }
      break;
      case DC_SIGCHAR_POINTER:
      {
        DCpointer ptr;
        if ( PyString_Check(po) ) {
          ptr = (DCpointer) PyString_AsString(po);
        } else if ( PyLong_Check(po) ) {
          ptr = (DCpointer) ( (DCint) PyLong_AsLongLong(po) );
        } else {
          return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a promoting pointer-type (int,string)", index );
        }
        dcArgPointer(gpCall, ptr );
      }
      break;
      case 'S':
      {
        char* p;
        if (!PyString_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a string", index );
        p = PyString_AsString(po);
        dcArgPointer(gpCall, (DCpointer) p );
      }
      break;
      default: return PyErr_Format( PyExc_RuntimeError, "unknown signature character '%c'", ch);
    }

    ++pos; ++ptr;

  }

  if (pos != l) return PyErr_Format( PyExc_RuntimeError, "too many arguments");

  if (ch == '\0') return PyErr_Format( PyExc_RuntimeError, "return value missing in signature");

  ch = *++ptr;

  switch(ch) 
  {
    case DC_SIGCHAR_VOID: dcCallVoid(gpCall, pfunc); Py_RETURN_NONE;
    case DC_SIGCHAR_BOOL: return Py_BuildValue("i", dcCallBool(gpCall, pfunc) );
    case DC_SIGCHAR_INT: return Py_BuildValue("i", dcCallInt(gpCall, pfunc) ); 
    case DC_SIGCHAR_LONGLONG: return Py_BuildValue("L", (unsigned long long) dcCallLongLong(gpCall, pfunc) );
    case DC_SIGCHAR_FLOAT: return Py_BuildValue("f", dcCallFloat(gpCall, pfunc) ); 
    case DC_SIGCHAR_DOUBLE: return Py_BuildValue("d", dcCallDouble(gpCall, pfunc) ); 
    case 's': return Py_BuildValue("s", dcCallPointer(gpCall, pfunc) ); 
    case DC_SIGCHAR_POINTER: return Py_BuildValue("p", dcCallPointer(gpCall, pfunc) ); 
    default:  return PyErr_Format( PyExc_RuntimeError, "invalid return type signature" );
  }
}
예제 #17
0
파일: api.c 프로젝트: svn2github/dyncall
SEXP r_dcCall(SEXP sCallVM, SEXP sFuncPtr, SEXP sSignature, SEXP sArgs)
{
  DCCallVM* pvm;
  void* funcPtr;
  const char* signature;
  const char* ptr;
  int i,l,protect_count;
  SEXP r;

  pvm = R_ExternalPtrAddr(sCallVM);
  if (!pvm) error("callvm is null");

  funcPtr = R_ExternalPtrAddr(sFuncPtr);
  if (!funcPtr) error("funcptr is null");

  signature = CHAR(STRING_ELT(sSignature,0) );
  if (!signature) error("signature is null");

  dcReset(pvm);
  ptr = signature;

  l = LENGTH(sArgs);
  i = 0;
  protect_count = 0;
  for(;;) {
    char ch = *ptr++;
    SEXP arg;

    if (ch == '\0') error("invalid signature - no return type specified");

    if (ch == ')') break;

    if (i >= l) error("not enough arguments for given signature (arg length = %d %d %c)", l,i,ch );

    arg = VECTOR_ELT(sArgs,i);
    switch(ch) {
      case DC_SIGCHAR_BOOL:
      {
    	DCbool value;
    	if ( isLogical(arg) )
    	{
    	  value = ( LOGICAL(arg)[0] == 0 ) ? DC_FALSE : DC_TRUE;
    	}
    	else
    	{
		  value = LOGICAL( coerceVector(arg, LGLSXP) )[0] ? DC_FALSE : DC_TRUE;
    	}
        dcArgBool(pvm, value );
        break;
      }
      case DC_SIGCHAR_INT:
      {
    	int value;
    	if ( isInteger(arg) )
    	{
    	  value = INTEGER(arg)[0];
    	}
    	else
    	{
    	  value = INTEGER( coerceVector(arg, INTSXP) )[0];
    	}
    	dcArgInt(pvm, value);
        break;
      }
      case DC_SIGCHAR_FLOAT:
      {
        dcArgFloat( pvm, (float) REAL( coerceVector(arg, REALSXP) )[0] );
        break;
      }
      case DC_SIGCHAR_DOUBLE:
      {
    	double value;
    	if ( isReal(arg) )
    	{
    		value = REAL(arg)[0];
    	}
    	else
    	{
			value = REAL( coerceVector(arg,REALSXP) )[0];
    	}
      	dcArgDouble( pvm, value );
      	break;
      }
      /*
      case DC_SIGCHAR_LONG:
      {
        PROTECT(arg = coerceVector(arg, REALSXP) );
        dcArgLong( pvm, (DClong) ( REAL(arg)[0] ) );
        UNPROTECT(1);
        break;
      }
      */
      case DC_SIGCHAR_STRING:
      {
        DCpointer ptr;
        if (arg == R_NilValue) ptr = (DCpointer) 0;
        else if (isString(arg)) ptr = (DCpointer) CHAR( STRING_ELT(arg,0) );
        else {
          if (protect_count) UNPROTECT(protect_count);
          error("invalid value for C string argument"); break;
        }
      }
      case DC_SIGCHAR_POINTER:
      {
        DCpointer ptr;
        if ( arg == R_NilValue )  ptr = (DCpointer) 0;
        else if (isString(arg) )  ptr = (DCpointer) CHAR( STRING_ELT(arg,0) );
        else if (isReal(arg) )    ptr = (DCpointer) REAL(arg);
        else if (isInteger(arg) ) ptr = (DCpointer) INTEGER(arg);
        else if (isLogical(arg) ) ptr = (DCpointer) LOGICAL(arg);
        else if (TYPEOF(arg) == EXTPTRSXP) ptr = R_ExternalPtrAddr(arg);
        else {
          if (protect_count) UNPROTECT(protect_count);
          error("invalid signature"); break;
        }
        dcArgPointer(pvm, ptr);
        break;
      }
    }
    ++i;
  }

  if ( i != l )
  {
    if (protect_count)
      UNPROTECT(protect_count);
    error ("signature claims to have %d arguments while %d arguments are given", i, l);
  }

  switch(*ptr) {
    case DC_SIGCHAR_BOOL:
      PROTECT( r = allocVector(LGLSXP, 1) ); protect_count++;
      LOGICAL(r)[0] = ( dcCallBool(pvm, funcPtr) == DC_FALSE ) ? FALSE : TRUE;
      UNPROTECT(protect_count);
      return r;
    case DC_SIGCHAR_CHAR:
        PROTECT( r = allocVector(INTSXP, 1) ); protect_count++;
        INTEGER(r)[0] = dcCallChar(pvm, funcPtr);
        UNPROTECT(protect_count);
        return r;
    case DC_SIGCHAR_SHORT:
        PROTECT( r = allocVector(INTSXP, 1) ); protect_count++;
        INTEGER(r)[0] = dcCallShort(pvm, funcPtr);
        UNPROTECT(protect_count);
        return r;
    case DC_SIGCHAR_LONG:
        PROTECT( r = allocVector(INTSXP, 1) ); protect_count++;
        INTEGER(r)[0] = dcCallLong(pvm, funcPtr);
        UNPROTECT(protect_count);
        return r;
    case DC_SIGCHAR_INT:
      PROTECT( r = allocVector(INTSXP, 1) ); protect_count++;
      INTEGER(r)[0] = dcCallInt(pvm, funcPtr);
      UNPROTECT(protect_count);
      return r;
    case DC_SIGCHAR_LONGLONG:
      PROTECT( r = allocVector(REALSXP, 1) ); protect_count++;
      REAL(r)[0] = (double) ( dcCallLong(pvm, funcPtr) );
      UNPROTECT(protect_count);
      return r;
    case DC_SIGCHAR_FLOAT:
      PROTECT( r = allocVector(REALSXP, 1) ); protect_count++;
      REAL(r)[0] = (double) ( dcCallFloat(pvm, funcPtr) );
      UNPROTECT(protect_count);
      return r;
    case DC_SIGCHAR_DOUBLE:
      PROTECT( r = allocVector(REALSXP, 1) );
      protect_count++;
      REAL(r)[0] = dcCallDouble(pvm, funcPtr);
      UNPROTECT(protect_count);
      return r;
    case DC_SIGCHAR_POINTER:
      PROTECT( r = R_MakeExternalPtr( dcCallPointer(pvm,funcPtr), R_NilValue, R_NilValue ) );
      protect_count++;
      UNPROTECT(protect_count);
      return r;
    case DC_SIGCHAR_VOID:
      dcCallVoid(pvm,funcPtr);
      if (protect_count) UNPROTECT(protect_count);
      break;
    default:
      {
        if (protect_count)
          UNPROTECT(protect_count);
        error("invalid return type signature");
      }
      break;
  }
  return R_NilValue;

}
예제 #18
0
파일: api.c 프로젝트: svn2github/dyncall
SEXP rdcMode(SEXP id)
{
  dcMode( gCall, INTEGER(id)[0] );
  dcReset( gCall );
  return R_NilValue;
}