Exemplo n.º 1
0
void*
jffi_getArray(JNIEnv* env, jobject buf, jsize offset, jsize length, int paramType,
        StackAllocator* stackAllocator, Array* array) 
{
    if (buf == NULL) {
        return NULL;
    }
    if ((paramType & ARRAY_PINNED) != 0) {
        return jffi_getArrayCritical(env, buf, offset, length, paramType, array);
    }
    switch (paramType & ARGPRIM_MASK) {
    case com_kenai_jffi_ObjectBuffer_BYTE:
        ARRAY(Byte, jbyte, paramType, buf, offset, length, array);
        // If the array was really a string, nul terminate it
        if ((paramType & (ARRAY_NULTERMINATE | ARRAY_IN | ARRAY_OUT)) != ARRAY_OUT) {
            if (array->elems != NULL) {
                *(((char *) array->elems) + length) = '\0';
            }
        }
        break;
    case com_kenai_jffi_ObjectBuffer_SHORT:
        ARRAY(Short, jshort, paramType, buf, offset, length, array);
        break;
    case com_kenai_jffi_ObjectBuffer_INT:
        ARRAY(Int, jint, paramType, buf, offset, length, array);
        break;
    case com_kenai_jffi_ObjectBuffer_LONG:
        ARRAY(Long, jlong, paramType, buf, offset, length, array);
        break;
    case com_kenai_jffi_ObjectBuffer_FLOAT:
        ARRAY(Float, jfloat, paramType, buf, offset, length, array);
        break;
    case com_kenai_jffi_ObjectBuffer_DOUBLE:
        ARRAY(Double, jdouble, paramType, buf, offset, length, array);
        break;
    default:
        throwException(env, IllegalArgument, "Invalid array type: %#x\n", paramType);
        return NULL;
    }
    array->array = buf;
    array->offset = offset;
    array->length = length;
    
    /* If its an IN-only array, don't bother copying the native data back. */
    array->mode = ((paramType & (ARRAY_IN | ARRAY_OUT)) == ARRAY_IN) ? JNI_ABORT : 0;
    return array->elems;
}
Exemplo n.º 2
0
static void
invokeArrayWithObjects_(JNIEnv* env, jlong ctxAddress, jbyteArray paramBuffer,
        jint objectCount, jint* infoBuffer, jobject* objectBuffer, void* retval)
{
    Function* ctx = (Function *) j2p(ctxAddress);
    jbyte *tmpBuffer = NULL;
    void **ffiArgs = NULL;
    Array *arrays = NULL;
    unsigned int i, arrayCount = 0, paramBytes = 0;

    arrays = alloca(objectCount * sizeof(Array));

#if defined(USE_RAW)
    paramBytes = ctx->rawParameterSize;
#else
    paramBytes = ctx->cif.nargs * PARAM_SIZE;
#endif

    tmpBuffer = alloca(paramBytes);
    (*env)->GetByteArrayRegion(env, paramBuffer, 0, paramBytes, tmpBuffer);

#ifndef USE_RAW
    ffiArgs = alloca(ctx->cif.nargs * sizeof(void *));
    
    for (i = 0; i < (unsigned int) ctx->cif.nargs; ++i) {
        ffiArgs[i] = &tmpBuffer[i * PARAM_SIZE];
    }
#endif    

    
    for (i = 0; i < (unsigned int) objectCount; ++i) {
        int type = infoBuffer[i * 3];
        jsize offset = infoBuffer[(i * 3) + 1];
        jsize length = infoBuffer[(i * 3) + 2];
        jobject object = objectBuffer[i];
        int idx = (type & com_kenai_jffi_ObjectBuffer_INDEX_MASK) >> com_kenai_jffi_ObjectBuffer_INDEX_SHIFT;
        void* ptr;

        switch (type & com_kenai_jffi_ObjectBuffer_TYPE_MASK & ~com_kenai_jffi_ObjectBuffer_PRIM_MASK) {
            case com_kenai_jffi_ObjectBuffer_ARRAY:
                if (unlikely(object == NULL)) {
                    throwException(env, NullPointer, "null object for parameter %d", idx);
                    goto cleanup;
                
                } else if (unlikely((type & com_kenai_jffi_ObjectBuffer_PINNED) != 0)) {

                    ptr = jffi_getArrayCritical(env, object, offset, length, type, &arrays[arrayCount]);
                    if (unlikely(ptr == NULL)) {
                        goto cleanup;
                    }
                } else if (true && likely(length < MAX_STACK_ARRAY)) {

                    ptr = alloca(jffi_arraySize(length + 1, type));
                    if (unlikely(jffi_getArrayBuffer(env, object, offset, length, type,
                        &arrays[arrayCount], ptr) == NULL)) {
                        goto cleanup;
                    }

                } else {
                    ptr = jffi_getArrayHeap(env, object, offset, length, type, &arrays[arrayCount]);
                    if (unlikely(ptr == NULL)) {
                        goto cleanup;
                    }
                }
                
                ++arrayCount;
                break;

            case com_kenai_jffi_ObjectBuffer_BUFFER:
                ptr = (*env)->GetDirectBufferAddress(env, object);
                if (unlikely(ptr == NULL)) {
                    throwException(env, NullPointer, "Could not get direct Buffer address");
                    goto cleanup;
                }
                ptr = ((char *) ptr + offset);
                break;

            case com_kenai_jffi_ObjectBuffer_JNI:
                switch (type & com_kenai_jffi_ObjectBuffer_TYPE_MASK) {
                    case com_kenai_jffi_ObjectBuffer_JNIENV:
                        ptr = env;
                        break;
                    case com_kenai_jffi_ObjectBuffer_JNIOBJECT:
                        ptr = (void *) object;
                        break;
                    default:
                        throwException(env, IllegalArgument, "Unsupported object type: %#x",
                            type & com_kenai_jffi_ObjectBuffer_TYPE_MASK);
                        goto cleanup;
                }
                
                break;
            default:
                throwException(env, IllegalArgument, "Unsupported object type: %#x", 
                        type & com_kenai_jffi_ObjectBuffer_TYPE_MASK);
                goto cleanup;
        }

#if defined(USE_RAW)
        *((void **)(tmpBuffer + ctx->rawParamOffsets[idx])) = ptr;
#else
        if (unlikely(ctx->cif.arg_types[idx]->type == FFI_TYPE_STRUCT)) {
            ffiArgs[idx] = ptr;
        } else {
            *((void **) ffiArgs[idx]) = ptr;
        }
#endif
    }
#if defined(USE_RAW)
    //
    // Special case for struct return values - unroll into a ptr array and
    // use ffi_call, since ffi_raw_call with struct return values is undocumented.
    //
    if (unlikely(ctx->cif.rtype->type == FFI_TYPE_STRUCT)) {
        ffiArgs = alloca(ctx->cif.nargs * sizeof(void *));
        for (i = 0; i < ctx->cif.nargs; ++i) {
            ffiArgs[i] = (tmpBuffer + ctx->rawParamOffsets[i]);
        }
        ffi_call(&ctx->cif, FFI_FN(ctx->function), retval, ffiArgs);
    } else {
        ffi_raw_call(&ctx->cif, FFI_FN(ctx->function), retval, (ffi_raw *) tmpBuffer);
    }
#else
    ffi_call(&ctx->cif, FFI_FN(ctx->function), retval, ffiArgs);
#endif
    SAVE_ERRNO(ctx);
cleanup:
    /* Release any array backing memory */
    for (i = 0; i < arrayCount; ++i) {
        if (arrays[i].release != NULL) {
            //printf("releasing array=%p\n", arrays[i].elems);
            (*arrays[i].release)(env, &arrays[i]);
        }
    }
}