コード例 #1
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;
}
コード例 #2
0
ファイル: dyncall_struct.c プロジェクト: MoarVM/dyncall
void dcArgStructUnroll(DCCallVM* vm, DCstruct* s, DCpointer  value)
{
	DCsize i;
	/*printf("UNROLLING STRUCT !\n");@@@*/
	assert(s && value);
	for (i = 0; i < s->fieldCount; i++) {
		DCfield *f = s->pFields + i;
		DCpointer p = (char*)value + f->offset;
		switch(f->type) {
		  case DC_SIGCHAR_STRUCT:
		  	dcArgStruct(vm, f->pSubStruct, p);
		  	break;
		  case DC_SIGCHAR_BOOL: 
			dcArgBool      (vm, *(DCbool*)p); 
			break;
		  case DC_SIGCHAR_CHAR:
		  case DC_SIGCHAR_UCHAR:
			dcArgChar      (vm, *(DCchar*)p);
			break;
		  case DC_SIGCHAR_SHORT:
		  case DC_SIGCHAR_USHORT:
			dcArgShort     (vm, *(DCshort*)p);
			break;
		  case DC_SIGCHAR_INT:
		  case DC_SIGCHAR_UINT:
			dcArgInt       (vm, *(DCint*)p);
			break;
		  case DC_SIGCHAR_LONG:
		  case DC_SIGCHAR_ULONG:
			dcArgLong      (vm, *(DCulong*)p);
			break;
		  case DC_SIGCHAR_LONGLONG:
		  case DC_SIGCHAR_ULONGLONG:
			dcArgLongLong  (vm, *(DCulonglong*)p);
			break;
		  case DC_SIGCHAR_FLOAT:
			dcArgFloat     (vm, *(DCfloat*)p);
			break;
		  case DC_SIGCHAR_DOUBLE:
			dcArgDouble    (vm, *(DCdouble*)p);
			break;
		  case DC_SIGCHAR_POINTER:
		  case DC_SIGCHAR_STRING:
			dcArgPointer   (vm, *(DCpointer**)p);
			break;
	       default:
	       	assert(0);
		}	
	}
}
コード例 #3
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;
}
コード例 #4
0
ファイル: dyncall_callf.c プロジェクト: Snaipe/dyncall
// 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;
    }
  }
}
コード例 #5
0
jboolean followArgs(CallTempStruct* call, DCArgs* args, int nTypes, ValueType* pTypes, jboolean toJava, jboolean isVarArgs)
{
    JNIEnv* env = call->env;
    int iParam;
    //printf("ARGS : %d args\n", (int)nTypes);
    for (iParam = 0; iParam < nTypes; iParam++) {
        ValueType type = pTypes[iParam];
        switch (type) {
        case eIntFlagSet:
        {
            jobject callIO = call && call->pCallIOs ? *(call->pCallIOs++) : NULL;
            if (toJava) {
                int flags = dcbArgInt(args);
                jobject obj = createPointerFromIO(env, JLONG_TO_PTR ((jlong)flags), callIO);
                dcArgPointer(call->vm, obj);
            } else {
                int arg = (jint)getFlagValue(env, (jobject)dcbArgPointer(args));
                if (isVarArgs)
                    dcArgPointer(call->vm, (void*)(ptrdiff_t)arg);
                else
                    dcArgInt(call->vm, arg);
            }
        }
        break;
        case eIntValue:
        {
            int arg = dcbArgInt(args);
            if (isVarArgs)
                dcArgPointer(call->vm, (void*)(ptrdiff_t)arg);
            else
                dcArgInt(call->vm, arg);
        }
        break;
#define ARG_BOXED_INTEGRAL(type, capitalized) \
{ \
	if (toJava) { \
		type arg = (sizeof(type) == 4) ? (type)dcbArgInt(args) : (type)dcbArgLongLong(args); \
		dcArgPointer(call->vm, Box ## capitalized(env, arg)); \
	} else { \
		jobject parg = dcbArgPointer(args); \
		jlong arg = Unbox ## capitalized(env, parg); \
		if (isVarArgs) \
			dcArgPointer(call->vm, (void*)(ptrdiff_t)arg); \
		else if (sizeof(type) == 4) \
			dcArgInt(call->vm, (jint)arg); \
		else \
			dcArgLongLong(call->vm, (jlong)arg); \
	} \
}
#define ARG_UNBOXED_INTEGRAL(type, capitalized) \
{ \
	if (toJava) { \
		type arg = (sizeof(type) == 4) ? (type)dcbArgInt(args) : (type)dcbArgLongLong(args); \
		dcArgLongLong(call->vm, (jlong)arg); \
	} else { \
		jlong arg = dcbArgLongLong(args); \
		if (isVarArgs) \
			dcArgPointer(call->vm, (void*)(ptrdiff_t)arg); \
		else if (sizeof(type) == 4) \
			dcArgInt(call->vm, (jint)arg); \
		else \
			dcArgLongLong(call->vm, (jlong)arg); \
	} \
}
        case eCLongValue:
            ARG_UNBOXED_INTEGRAL(long, CLong);
            break;
        case eSizeTValue:
            ARG_UNBOXED_INTEGRAL(size_t, SizeT);
            break;
        case eCLongObjectValue:
            ARG_BOXED_INTEGRAL(long, CLong);
            break;
        case eSizeTObjectValue:
            ARG_BOXED_INTEGRAL(size_t, SizeT);
            break;
        case eTimeTObjectValue:
            ARG_BOXED_INTEGRAL(time_t, TimeT);
            break;
        case eLongValue:
            dcArgLongLong(call->vm, dcbArgLongLong(args));
            break;
        case eShortValue:
        {
            short arg = dcbArgShort(args);
            if (isVarArgs)
                dcArgPointer(call->vm, (void*)(ptrdiff_t)arg);
            else
                dcArgShort(call->vm, arg);
        }
        break;
        case eBooleanValue:
        case eByteValue:
        {
            char arg = dcbArgChar(args);
            if (isVarArgs)
                dcArgPointer(call->vm, (void*)(ptrdiff_t)arg);
            else
                dcArgChar(call->vm, arg);
        }
        break;
        case eFloatValue:
        {
            float arg = dcbArgFloat(args);
            if (isVarArgs)
                dcArgDouble(call->vm, arg);
            else
                dcArgFloat(call->vm, arg);
        }
        break;
        case eDoubleValue:
            dcArgDouble(call->vm, dcbArgDouble(args));
            break;
        case ePointerValue:
        {
            void* ptr = dcbArgPointer(args);
            jobject callIO = call && call->pCallIOs ? *(call->pCallIOs++) : NULL;
            if (toJava)
            {
                ptr = createPointerFromIO(env, ptr, callIO);
            } else {
                ptr = ptr ? getPointerPeer(env, ptr) : NULL;
                // printf("ARG POINTER = %d\n", ptr);
            }
            dcArgPointer(call->vm, ptr);
        }
        break;
        case eWCharValue:
            switch (sizeof(wchar_t)) {
            case 1:
                dcArgChar(call->vm, dcbArgChar(args));
                break;
            case 2:
                dcArgShort(call->vm, dcbArgShort(args));
                break;
            case 4:
                dcArgInt(call->vm, dcbArgInt(args));
                break;
            default:
                throwException(env, "Invalid wchar_t size for argument !");
                return JNI_FALSE;
            }
            break;
        case eEllipsis: {
            if (toJava) {
                throwException(env, "Calling Java ellipsis is not supported yet !");
                return JNI_FALSE;
            } else {
                jobjectArray arr = (jobjectArray)dcbArgPointer(args);
                jsize n = (*env)->GetArrayLength(env, arr), i;

                for (i = 0; i < n; i++) {
                    jobject arg = (*env)->GetObjectArrayElement(env, arr, i);
#define TEST_INSTANCEOF(cl, st) \
			if ((*env)->IsInstanceOf(env, arg, cl)) st;

                    if (arg == NULL)
                        dcArgPointer(call->vm, getPointerPeer(env, (void*)NULL));
                    else
                        // As per the C standard for varargs, all ints are promoted to ptrdiff_t and float is promoted to double :
                        TEST_INSTANCEOF(gIntClass, dcArgPointer(call->vm, (void*)(ptrdiff_t)UnboxInt(env, arg)))
                        else
                            TEST_INSTANCEOF(gLongClass, dcArgPointer(call->vm, (void*)(ptrdiff_t)UnboxLong(env, arg)))
                            else
                                TEST_INSTANCEOF(gShortClass, dcArgPointer(call->vm, (void*)(ptrdiff_t)UnboxShort(env, arg)))
                                else
                                    TEST_INSTANCEOF(gByteClass, dcArgPointer(call->vm, (void*)(ptrdiff_t)UnboxByte(env, arg)))
                                    else
                                        TEST_INSTANCEOF(gBooleanClass, dcArgPointer(call->vm, (void*)(ptrdiff_t)(char)UnboxBoolean(env, arg)))
                                        else
                                            TEST_INSTANCEOF(gCharClass, dcArgPointer(call->vm, (void*)(ptrdiff_t)(short)UnboxChar(env, arg)))
                                            else
                                                TEST_INSTANCEOF(gDoubleClass, dcArgDouble(call->vm, UnboxDouble(env, arg)))
                                                else
                                                    TEST_INSTANCEOF(gFloatClass, dcArgDouble(call->vm, UnboxFloat(env, arg)))
                                                    else
                                                        TEST_INSTANCEOF(gCLongClass, dcArgPointer(call->vm, (void*)(ptrdiff_t)(long)UnboxCLong(env, arg)))
                                                        else
                                                            TEST_INSTANCEOF(gSizeTClass, dcArgPointer(call->vm, (void*)(ptrdiff_t)UnboxSizeT(env, arg)))
                                                            else
                                                                TEST_INSTANCEOF(gPointerClass, dcArgPointer(call->vm, getPointerPeer(env, (void*)arg)))
                                                                else {
                                                                    throwException(env, "Invalid value type in ellipsis");
                                                                    return JNI_FALSE;
                                                                }
                }
            }
            break;
        }
        default:
            throwException(env, "Invalid argument value type !");
            return JNI_FALSE;
        }
    }
    if ((*env)->ExceptionCheck(env))
        return JNI_FALSE;
    return JNI_TRUE;
}
コード例 #6
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;
}
コード例 #7
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;

}
コード例 #8
0
ファイル: dll.cpp プロジェクト: jespo655/Compiler
template<> void _push_fn_arg<float>(float value) { dcArgFloat(vm, value); }
コード例 #9
0
ファイル: pydcext.c プロジェクト: svn2github/dyncall
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" );
  }
}