public boolean matchesSignature(Method method) {

      if (getArgumentsStackSize() != null
          && getArgumentsStackSize().intValue() != getArgumentsStackSize(method)) {
        return false;
      }

      if (getMemberName() != null && !getMemberName().toString().equals(getMethodName(method))) {
        return false;
      }

      if (getValueType() != null
          && !getValueType().matches(method.getReturnType(), annotations(method))) {
        return false;
      }

      Template temp = method.getAnnotation(Template.class);
      Annotation[][] anns = method.getParameterAnnotations();
      //            Class<?>[] methodArgTypes = method.getParameterTypes();
      Type[] parameterTypes = method.getGenericParameterTypes();
      // boolean hasThisAsFirstArgument = BridJ.hasThisAsFirstArgument(method);//methodArgTypes,
      // anns, true);

      if (paramTypes != null
          && !matchesArgs(
              parameterTypes,
              anns,
              temp == null ? 0 : temp.value().length)) // /*, hasThisAsFirstArgument*/))
      {
        return false;
      }

      // int thisDirac = hasThisAsFirstArgument ? 1 : 0;
      /*
      switch (type) {
      case Constructor:
      case Destructor:
      Annotation ann = method.getAnnotation(type == SpecialName.Constructor ? Constructor.class : Destructor.class);
      if (ann == null)
      return false;
      if (!hasThisAsFirstArgument)
      return false;
      if (methodArgTypes.length - thisDirac != 0 )
      return false;
      break;
      case InstanceMethod:
      if (!hasThisAsFirstArgument)
      return false;
      break;
      case StaticMethod:
      if (hasThisAsFirstArgument)
      return false;
      break;
      }*/

      return true;
    }
 static int getArgumentsStackSize(Method method) {
   int total = 0;
   Type[] paramTypes = method.getGenericParameterTypes();
   Annotation[][] anns = method.getParameterAnnotations();
   for (int iArg = 0, nArgs = paramTypes.length; iArg < nArgs; iArg++) {
     Class<?> paramType = getTypeClass(paramTypes[iArg]);
     if (paramType == int.class) {
       total += 4;
     } else if (paramType == long.class) {
       Annotation[] as = anns[iArg];
       if (isAnnotationPresent(Ptr.class, as)
           || isAnnotationPresent(
               org.bridj.ann.CLong.class,
               as)) // if (hasInstance(anns[iArg], Ptr.class, CLong.class))
       {
         total += Pointer.SIZE;
       } else {
         total += 8;
       }
     } else if (paramType == float.class) {
       total += 4;
     } else if (paramType == double.class) {
       total += 8;
     } else if (paramType == byte.class) {
       total += 1;
     } else if (paramType == char.class) {
       total += Platform.WCHAR_T_SIZE;
     } else if (paramType == CLong.class) {
       total += Platform.CLONG_SIZE;
     } else if (paramType == SizeT.class) {
       total += Platform.SIZE_T_SIZE;
     } else if (paramType == TimeT.class) {
       total += Platform.TIME_T_SIZE;
     } else if (paramType == short.class) {
       total += 2;
     } else if (paramType == boolean.class) {
       total += 1;
     } else if (Pointer.class.isAssignableFrom(paramType)) {
       total += Pointer.SIZE;
     } else if (NativeObject.class.isAssignableFrom(paramType)) {
       total += ((CRuntime) BridJ.getRuntime(paramType)).sizeOf(paramTypes[iArg], null);
     } else if (FlagSet.class.isAssignableFrom(paramType)) {
       total += 4; // TODO
     } else {
       throw new RuntimeException("Type not handled : " + paramType.getName());
     }
   }
   return total;
 }
  public MethodCallInfo(Method method, Method definition) {
    this.setMethod(method);
    // this.setDefinition(definition);
    this.setDeclaringClass(method.getDeclaringClass());
    symbolName = methodName;

    int modifiers = method.getModifiers();
    isStatic = Modifier.isStatic(modifiers);
    isVarArgs = method.isVarArgs();
    boolean isNative = Modifier.isNative(modifiers);
    boolean isVirtual = isAnnotationPresent(Virtual.class, definition);
    boolean isDirectModeAllowed =
        getInheritableAnnotation(DisableDirect.class, definition) == null
            && BridJ.isDirectModeEnabled();

    isCPlusPlus = !isStatic && derivesFrom(method.getDeclaringClass(), "org.bridj.cpp.CPPObject");
    isObjCBlock = !isStatic && derivesFrom(method.getDeclaringClass(), "org.bridj.objc.ObjCBlock");

    init(
        method,
        method.getReturnType(),
        method.getGenericReturnType(),
        method.getAnnotations(),
        method.getParameterTypes(),
        method.getGenericParameterTypes(),
        method.getParameterAnnotations(),
        isNative,
        isVirtual,
        isDirectModeAllowed);

    Convention cc = getInheritableAnnotation(Convention.class, definition);
    if (cc != null) {
      setCallingConvention(cc.value());
    }
    List<Class<?>> exceptionTypes = Arrays.asList(definition.getExceptionTypes());
    if (!exceptionTypes.isEmpty()) {
      this.direct = false; // there is no crash / exception protection for direct raw calls
      if (exceptionTypes.contains(LastError.class)) this.bThrowLastError = true;
    }
  }