Пример #1
0
 /** @see NativeLibrary#NativeLibrary(String,String,long,Map) implementation */
 Object invoke(Object[] args, Class returnType, boolean allowObjects) {
   Object result = null;
   if (returnType == null || returnType == void.class || returnType == Void.class) {
     Native.invokeVoid(peer, callFlags, args);
     result = null;
   } else if (returnType == boolean.class || returnType == Boolean.class) {
     result = valueOf(Native.invokeInt(peer, callFlags, args) != 0);
   } else if (returnType == byte.class || returnType == Byte.class) {
     result = new Byte((byte) Native.invokeInt(peer, callFlags, args));
   } else if (returnType == short.class || returnType == Short.class) {
     result = new Short((short) Native.invokeInt(peer, callFlags, args));
   } else if (returnType == char.class || returnType == Character.class) {
     result = new Character((char) Native.invokeInt(peer, callFlags, args));
   } else if (returnType == int.class || returnType == Integer.class) {
     result = new Integer(Native.invokeInt(peer, callFlags, args));
   } else if (returnType == long.class || returnType == Long.class) {
     result = new Long(Native.invokeLong(peer, callFlags, args));
   } else if (returnType == float.class || returnType == Float.class) {
     result = new Float(Native.invokeFloat(peer, callFlags, args));
   } else if (returnType == double.class || returnType == Double.class) {
     result = new Double(Native.invokeDouble(peer, callFlags, args));
   } else if (returnType == String.class) {
     result = invokeString(callFlags, args, false);
   } else if (returnType == WString.class) {
     String s = invokeString(callFlags, args, true);
     if (s != null) {
       result = new WString(s);
     }
   } else if (Pointer.class.isAssignableFrom(returnType)) {
     return invokePointer(callFlags, args);
   } else if (Structure.class.isAssignableFrom(returnType)) {
     if (Structure.ByValue.class.isAssignableFrom(returnType)) {
       Structure s =
           Native.invokeStructure(peer, callFlags, args, Structure.newInstance(returnType));
       s.autoRead();
       result = s;
     } else {
       result = invokePointer(callFlags, args);
       if (result != null) {
         Structure s = Structure.newInstance(returnType, (Pointer) result);
         s.conditionalAutoRead();
         result = s;
       }
     }
   } else if (Callback.class.isAssignableFrom(returnType)) {
     result = invokePointer(callFlags, args);
     if (result != null) {
       result = CallbackReference.getCallback(returnType, (Pointer) result);
     }
   } else if (returnType == String[].class) {
     Pointer p = invokePointer(callFlags, args);
     if (p != null) {
       result = p.getStringArray(0, encoding);
     }
   } else if (returnType == WString[].class) {
     Pointer p = invokePointer(callFlags, args);
     if (p != null) {
       String[] arr = p.getWideStringArray(0);
       WString[] warr = new WString[arr.length];
       for (int i = 0; i < arr.length; i++) {
         warr[i] = new WString(arr[i]);
       }
       result = warr;
     }
   } else if (returnType == Pointer[].class) {
     Pointer p = invokePointer(callFlags, args);
     if (p != null) {
       result = p.getPointerArray(0);
     }
   } else if (allowObjects) {
     result = Native.invokeObject(peer, callFlags, args);
     if (result != null && !returnType.isAssignableFrom(result.getClass())) {
       throw new ClassCastException(
           "Return type " + returnType + " does not match result " + result.getClass());
     }
   } else {
     throw new IllegalArgumentException(
         "Unsupported return type " + returnType + " in function " + getName());
   }
   return result;
 }
Пример #2
0
  /**
   * Invoke the native function with the given arguments, returning the native result as an Object.
   */
  public Object invoke(Class returnType, Object[] inArgs, Map options) {
    // Clone the argument array to obtain a scratch space for modified
    // types/values
    Object[] args = {};
    if (inArgs != null) {
      if (inArgs.length > MAX_NARGS) {
        throw new UnsupportedOperationException("Maximum argument count is " + MAX_NARGS);
      }
      args = new Object[inArgs.length];
      System.arraycopy(inArgs, 0, args, 0, args.length);
    }

    TypeMapper mapper = (TypeMapper) options.get(Library.OPTION_TYPE_MAPPER);
    Method invokingMethod = (Method) options.get(OPTION_INVOKING_METHOD);
    Class[] paramTypes = invokingMethod != null ? invokingMethod.getParameterTypes() : null;
    boolean allowObjects = Boolean.TRUE.equals(options.get(Library.OPTION_ALLOW_OBJECTS));
    boolean isVarArgs =
        args.length > 0 && invokingMethod != null ? isVarArgs(invokingMethod) : false;
    for (int i = 0; i < args.length; i++) {
      Class paramType =
          invokingMethod != null
              ? (isVarArgs && i >= paramTypes.length - 1
                  ? paramTypes[paramTypes.length - 1].getComponentType()
                  : paramTypes[i])
              : null;
      args[i] = convertArgument(args, i, invokingMethod, mapper, allowObjects, paramType);
    }

    Class nativeReturnType = returnType;
    FromNativeConverter resultConverter = null;
    if (NativeMapped.class.isAssignableFrom(returnType)) {
      NativeMappedConverter tc = NativeMappedConverter.getInstance(returnType);
      resultConverter = tc;
      nativeReturnType = tc.nativeType();
    } else if (mapper != null) {
      resultConverter = mapper.getFromNativeConverter(returnType);
      if (resultConverter != null) {
        nativeReturnType = resultConverter.nativeType();
      }
    }

    Object result = invoke(args, nativeReturnType, allowObjects);

    // Convert the result to a custom value/type if appropriate
    if (resultConverter != null) {
      FromNativeContext context;
      if (invokingMethod != null) {
        context = new MethodResultContext(returnType, this, inArgs, invokingMethod);
      } else {
        context = new FunctionResultContext(returnType, this, inArgs);
      }
      result = resultConverter.fromNative(result, context);
    }

    // Sync all memory which might have been modified by the native call
    if (inArgs != null) {
      for (int i = 0; i < inArgs.length; i++) {
        Object inArg = inArgs[i];
        if (inArg == null) continue;
        if (inArg instanceof Structure) {
          if (!(inArg instanceof Structure.ByValue)) {
            ((Structure) inArg).autoRead();
          }
        } else if (args[i] instanceof PostCallRead) {
          ((PostCallRead) args[i]).read();
          if (args[i] instanceof PointerArray) {
            PointerArray array = (PointerArray) args[i];
            if (Structure.ByReference[].class.isAssignableFrom(inArg.getClass())) {
              Class type = inArg.getClass().getComponentType();
              Structure[] ss = (Structure[]) inArg;
              for (int si = 0; si < ss.length; si++) {
                Pointer p = array.getPointer(Pointer.SIZE * si);
                ss[si] = Structure.updateStructureByReference(type, ss[si], p);
              }
            }
          }
        } else if (Structure[].class.isAssignableFrom(inArg.getClass())) {
          Structure.autoRead((Structure[]) inArg);
        }
      }
    }

    return result;
  }