static void invokeArray(JNIEnv* env, jlong ctxAddress, jbyteArray paramBuffer, void* returnBuffer) { Function* ctx = (Function *) j2p(ctxAddress); union { double d; long long ll; jbyte tmp[PARAM_SIZE]; } tmpStackBuffer[MAX_STACK_ARGS]; jbyte *tmpBuffer = (jbyte *) &tmpStackBuffer[0]; if (ctx->cif.nargs > 0) { if (ctx->cif.bytes > (int) sizeof(tmpStackBuffer)) { tmpBuffer = alloca_aligned(ctx->cif.bytes, MIN_ALIGN); } // calculate room needed for return address for struct returns int adj = ctx->cif.rtype->type == FFI_TYPE_STRUCT ? sizeof(void *) : 0; (*env)->GetByteArrayRegion(env, paramBuffer, 0, ctx->rawParameterSize, tmpBuffer + adj); } // For struct return values, we need to push a return value address on the parameter stack if (ctx->cif.rtype->type == FFI_TYPE_STRUCT) { *(void **) tmpBuffer = returnBuffer; } ffi_raw_call(&ctx->cif, FFI_FN(ctx->function), returnBuffer, (ffi_raw *) tmpBuffer); set_last_error(errno); }
static void invokeArray(JNIEnv* env, jlong ctxAddress, jbyteArray paramBuffer, void* returnBuffer) { Function* ctx = (Function *) j2p(ctxAddress); union { double d; long long ll; jbyte tmp[PARAM_SIZE]; } tmpStackBuffer[MAX_STACK_ARGS]; jbyte *tmpBuffer = (jbyte *) &tmpStackBuffer[0]; void* ffiStackArgs[MAX_STACK_ARGS]; void** ffiArgs = ffiStackArgs; if (ctx->cif.nargs > 0) { unsigned int i; if (ctx->cif.nargs > MAX_STACK_ARGS) { tmpBuffer = alloca_aligned(ctx->cif.nargs * PARAM_SIZE, MIN_ALIGN); ffiArgs = alloca_aligned(ctx->cif.nargs * sizeof(void *), MIN_ALIGN); } (*env)->GetByteArrayRegion(env, paramBuffer, 0, ctx->cif.nargs * PARAM_SIZE, tmpBuffer); for (i = 0; i < ctx->cif.nargs; ++i) { if (ctx->cif.arg_types[i]->type == FFI_TYPE_STRUCT) { ffiArgs[i] = *(void **) &tmpBuffer[i * PARAM_SIZE]; } else { ffiArgs[i] = &tmpBuffer[i * PARAM_SIZE]; } } } ffi_call(&ctx->cif, FFI_FN(ctx->function), returnBuffer, ffiArgs); set_last_error(errno); }
static void invokeArray(JNIEnv* env, jlong ctxAddress, jbyteArray paramBuffer, void* returnBuffer) { Function* ctx = (Function *) j2p(ctxAddress); void** ffiArgs = { NULL }; jbyte *tmpBuffer = NULL; if (ctx->cif.nargs > 0) { unsigned int i; tmpBuffer = alloca(ctx->cif.nargs * PARAM_SIZE); ffiArgs = alloca(ctx->cif.nargs * sizeof(void *)); (*env)->GetByteArrayRegion(env, paramBuffer, 0, ctx->cif.nargs * PARAM_SIZE, tmpBuffer); for (i = 0; i < ctx->cif.nargs; ++i) { if (unlikely(ctx->cif.arg_types[i]->type == FFI_TYPE_STRUCT)) { ffiArgs[i] = *(void **) &tmpBuffer[i * PARAM_SIZE]; } else { ffiArgs[i] = &tmpBuffer[i * PARAM_SIZE]; } } } ffi_call(&ctx->cif, FFI_FN(ctx->function), returnBuffer, ffiArgs); SAVE_ERRNO(ctx); }
pid_t fbg_argv_to_pid(char **argv) { pid_t pid = 0; int jid = 0; char *p = argv[1]; if (argv[1] == NULL || argv[2] != NULL) return 0; if (*p != '%' && (*p < '0' || *p > '9')) return 0; if (*p == '%' && *(p + 1) == 0) return 0; for (p += 1; *p != 0; p++) if (*p < '0' || *p > '9') return 0; p = argv[1]; if (*p == '%') { if ((jid = atoi(p + 1)) < 1) return 0; if ((pid = j2p(jid)) < 1) { printf("no such process\n"); return 0; } return pid; } if ((pid = atoi(p)) < 1) return 0; if (selectjob(pid) == NULL) { printf("no such process\n"); return 0; } return pid; }
/* * Class: com_kenai_jffi_Foreign * Method: invokeArrayReturnStruct * Signature: (J[B[B)V */ JNIEXPORT void JNICALL Java_com_kenai_jffi_Foreign_invokeArrayReturnStruct(JNIEnv* env, jclass self, jlong ctxAddress, jbyteArray paramBuffer, jbyteArray returnBuffer, jint offset) { Function* ctx = (Function *) j2p(ctxAddress); jbyte* retval = alloca(ctx->cif.rtype->size); jbyte* tmpBuffer; void** ffiArgs; int i; // // Due to the undocumented and somewhat strange struct-return handling when // using ffi_raw_call(), we convert from raw to ptr array, then call via normal // ffi_call // ffiArgs = alloca(ctx->cif.nargs * sizeof(void *)); #ifdef USE_RAW tmpBuffer = alloca(ctx->rawParameterSize); (*env)->GetByteArrayRegion(env, paramBuffer, 0, ctx->rawParameterSize, tmpBuffer); for (i = 0; i < (int) ctx->cif.nargs; ++i) { ffiArgs[i] = (tmpBuffer + ctx->rawParamOffsets[i]); } #else tmpBuffer = alloca(ctx->cif.nargs * PARAM_SIZE); (*env)->GetByteArrayRegion(env, paramBuffer, 0, ctx->cif.nargs * PARAM_SIZE, tmpBuffer); for (i = 0; i < (int) ctx->cif.nargs; ++i) { ffiArgs[i] = &tmpBuffer[i * PARAM_SIZE]; } #endif ffi_call(&ctx->cif, FFI_FN(ctx->function), retval, ffiArgs); SAVE_ERRNO(ctx); (*env)->SetByteArrayRegion(env, returnBuffer, offset, ctx->cif.rtype->size, retval); }
static PyObject *t_Field_getName(t_Field *self) { String name((jobject) NULL); OBJ_CALL(name = self->object.getName()); return j2p(name); }
/* * Class: com_kenai_jffi_Foreign * Method: VirtualFree * Signature: (JI)Z */ JNIEXPORT jboolean JNICALL Java_com_kenai_jffi_Foreign_VirtualFree(JNIEnv *env, jobject self, jlong addr, jint size, jint flags) { if (!VirtualFree(j2p(addr), size, flags)) { jffi_save_errno(); return JNI_FALSE; } return JNI_TRUE; }
JNIEXPORT jlong JNICALL Java_com_kenai_jffi_Foreign_dlsym(JNIEnv* env, jclass cls, jlong handle, jstring jstr) { char sym[1024]; getMultibyteString(env, sym, jstr, sizeof(sym)); #ifndef _WIN32 dlerror(); // clear any errors #endif return p2j(dl_sym(j2p(handle), sym)); }
/* * Class: com_kenai_jffi_Foreign * Method: invokeArrayReturnStruct * Signature: (J[B[B)V */ JNIEXPORT void JNICALL Java_com_kenai_jffi_Foreign_invokeArrayReturnStruct(JNIEnv* env, jclass self, jlong ctxAddress, jbyteArray paramBuffer, jbyteArray returnBuffer, jint offset) { Function* ctx = (Function *) j2p(ctxAddress); jbyte* retval = alloca_aligned(ctx->cif.rtype->size, MIN_ALIGN); invokeArray(env, ctxAddress, paramBuffer, retval); (*env)->SetByteArrayRegion(env, returnBuffer, offset, ctx->cif.rtype->size, retval); }
/* * Class: com_kenai_jffi_Foreign * Method: mprotect * Signature: (JJI)I */ JNIEXPORT jint JNICALL Java_com_kenai_jffi_Foreign_mprotect(JNIEnv *env, jobject self, jlong addr, jlong len, jint prot) { int result = mprotect(j2p(addr), len, PROT(prot)); if (unlikely(result != 0)) { jffi_save_errno(); return -1; } return 0; }
/* * Class: com_kenai_jffi_Foreign * Method: VirtualAlloc * Signature: (JIII)J */ JNIEXPORT jlong JNICALL Java_com_kenai_jffi_Foreign_VirtualAlloc(JNIEnv *env, jobject self, jlong addr, jint size, jint flags, jint prot) { void* ptr = VirtualAlloc(j2p(addr), size, flags, prot); if (unlikely(ptr == NULL)) { jffi_save_errno(); return 0; } return p2j(ptr); }
/* * Class: com_kenai_jffi_Foreign * Method: VirtualProtect * Signature: (JII)Z */ JNIEXPORT jboolean JNICALL Java_com_kenai_jffi_Foreign_VirtualProtect(JNIEnv *env, jobject self, jlong addr, jint size, jint prot) { DWORD oldprot; if (!VirtualProtect(j2p(addr), size, prot, &oldprot)) { jffi_save_errno(); return JNI_FALSE; } return JNI_TRUE; }
/* * Class: com_kenai_jffi_Foreign * Method: invokeArrayWithObjectsReturnStruct * Signature: (J[BI[I[Ljava/lang/Object;[BI)V */ JNIEXPORT void JNICALL Java_com_kenai_jffi_Foreign_invokeArrayWithObjectsReturnStruct(JNIEnv* env, jobject self, jlong ctxAddress, jbyteArray paramBuffer, jint objectCount, jintArray objectInfo, jobjectArray objectArray, jbyteArray returnBuffer, jint returnBufferOffset) { Function* ctx = (Function *) j2p(ctxAddress); jbyte* retval = alloca(ctx->cif.rtype->size); invokeArrayWithObjects(env, ctxAddress, paramBuffer, objectCount, objectInfo, objectArray, retval); (*env)->SetByteArrayRegion(env, returnBuffer, returnBufferOffset, ctx->cif.rtype->size, retval); }
/* * Class: com_kenai_jffi_Foreign * Method: munmap * Signature: (JJ)I */ JNIEXPORT jint JNICALL Java_com_kenai_jffi_Foreign_munmap(JNIEnv *env, jobject self, jlong addr, jlong len) { int result = munmap(j2p(addr), len); if (unlikely(result != 0)) { jffi_save_errno(); return -1; } return 0; }
/* * Class: com_kenai_jffi_Foreign * Method: freeStruct * Signature: (J)V */ JNIEXPORT void JNICALL Java_com_kenai_jffi_Foreign_freeStruct(JNIEnv* env, jobject self, jlong handle) { ffi_type* s = (ffi_type *) j2p(handle); if (s != NULL) { if (s->elements != NULL) { free(s->elements); } free(s); } }
/* * Class: com_kenai_jffi_Foreign * Method: mmap * Signature: (JJIIIJ)J */ JNIEXPORT jlong JNICALL Java_com_kenai_jffi_Foreign_mmap(JNIEnv *env, jobject self, jlong addr, jlong len, jint prot, jint flags, jint fd, jlong off) { caddr_t result; result = mmap(j2p(addr), len, PROT(prot), FLAGS(flags), fd, off); if (unlikely(result == (caddr_t) -1)) { jffi_save_errno(); return -1; } return p2j(result); }
/* * Class: com_kenai_jffi_Foreign * Method: invokePointerParameterArray * Signature: (JJ[J)V */ JNIEXPORT void JNICALL Java_com_kenai_jffi_Foreign_invokePointerParameterArray(JNIEnv *env, jobject self, jlong ctxAddress, jlong returnBuffer, jlongArray parameterArray) { Function* ctx = (Function *) j2p(ctxAddress); int parameterCount; jlong* params = NULL; void** ffiArgs = NULL; int i; if (unlikely(ctxAddress == 0LL)) { throwException(env, NullPointer, "context address is null"); return; } if (unlikely(returnBuffer == 0LL)) { throwException(env, NullPointer, "result buffer is null"); return; } if (unlikely(parameterArray == NULL)) { throwException(env, NullPointer, "parameter array is null"); return; } parameterCount = (*env)->GetArrayLength(env, parameterArray); if (parameterCount > 0) { params = alloca(parameterCount * sizeof(jlong)); ffiArgs = alloca(parameterCount * sizeof(void *)); (*env)->GetLongArrayRegion(env, parameterArray, 0, parameterCount, params); for (i = 0; i < parameterCount; ++i) { ffiArgs[i] = j2p(params[i]); } } ffi_call(&ctx->cif, FFI_FN(ctx->function), j2p(returnBuffer), ffiArgs); }
/* * Class: com_kenai_jffi_Foreign * Method: freeClosureMagazine * Signature: (J)V */ JNIEXPORT void JNICALL Java_com_kenai_jffi_Foreign_freeClosureMagazine(JNIEnv *env, jobject self, jlong magAddress) { Magazine* magazine = (Magazine *) j2p(magAddress); Closure* closure; int i; for (i = 0; i < magazine->nextclosure; ++i) { (*env)->DeleteGlobalRef(env, magazine->closures[i].javaObject); } free(magazine->closures); jffi_freePages(magazine->code, 1); free(magazine); }
static void invokeArray(JNIEnv* env, jlong ctxAddress, jbyteArray paramBuffer, void* returnBuffer) { Function* ctx = (Function *) j2p(ctxAddress); FFIValue tmpValue; jbyte *tmpBuffer = (jbyte *) &tmpValue; if (likely(ctx->cif.nargs > 0)) { tmpBuffer = alloca(ctx->cif.bytes); (*env)->GetByteArrayRegion(env, paramBuffer, 0, ctx->rawParameterSize, tmpBuffer); } ffi_raw_call(&ctx->cif, FFI_FN(ctx->function), returnBuffer, (ffi_raw *) tmpBuffer); SAVE_ERRNO(ctx); }
/* * Class: com_kenai_jffi_Foreign * Method: closureMagazineGet * Signature: (JLjava/lang/Object;)J */ JNIEXPORT jlong JNICALL Java_com_kenai_jffi_Foreign_closureMagazineGet(JNIEnv *env, jobject self, jlong magAddress, jobject closureProxy) { Magazine* magazine = (Magazine *) j2p(magAddress); if (magazine->nextclosure < magazine->nclosures) { Closure* closure = &magazine->closures[magazine->nextclosure]; closure->javaObject = (*env)->NewGlobalRef(env, closureProxy); if (closure->javaObject == NULL) { throwException(env, IllegalArgument, "could not obtain reference to java object"); return 0L; } magazine->nextclosure++; return p2j(closure); } return 0L; }
JNIEXPORT jlong JNICALL Java_com_kenai_jffi_Foreign_dlsym(JNIEnv* env, jclass cls, jlong handle, jstring jstr) { char sym[1024]; void* addr; getMultibyteString(env, sym, jstr, sizeof(sym)); #ifndef _WIN32 dlerror(); // clear any errors #endif addr = dl_sym(j2p(handle), sym); if (addr == NULL) { char errbuf[1024] = { 0 }; dl_error(errbuf, sizeof(errbuf) - 1); throwException(env, UnsatisfiedLink, "%s", errbuf); } return p2j(addr); }
/* * Class: com_kenai_jffi_Foreign * Method: getTypeType * Signature: (J)I */ JNIEXPORT jint JNICALL Java_com_kenai_jffi_Foreign_getTypeType(JNIEnv* env, jobject self, jlong handle) { return ((ffi_type *) j2p(handle))->type; }
/* * Class: com_googlecode_jffi_NativeLibrary * Method: dlclose * Signature: (J)V */ JNIEXPORT void JNICALL Java_com_kenai_jffi_Foreign_dlclose(JNIEnv* env, jclass cls, jlong handle) { dl_close(j2p(handle)); }
JNIEXPORT jint JNICALL Java_com_kenai_jffi_Foreign_registerNatives(JNIEnv *env, jobject self, jclass clazz, jlong methods, jint nmethods) { return (*env)->RegisterNatives(env, clazz, j2p(methods), nmethods); }
static void invokeArrayWithObjects_(JNIEnv* env, jlong ctxAddress, jbyteArray paramBuffer, jint objectCount, jint* infoBuffer, jobject* objectBuffer, void* retval) { Function* ctx = (Function *) j2p(ctxAddress); union { double d; long long ll; jbyte tmp[PARAM_SIZE]; } tmpStackBuffer[MAX_STACK_ARGS]; jbyte *tmpBuffer = (jbyte *) &tmpStackBuffer[0]; #if defined(USE_RAW) int rawAdj = ctx->cif.rtype->type == FFI_TYPE_STRUCT ? sizeof(void *) : 0; #else void* ffiStackArgs[MAX_STACK_ARGS], **ffiArgs = &ffiStackArgs[0]; #endif Array stackArrays[MAX_STACK_OBJECTS], *arrays = &stackArrays[0]; StackAllocator alloc; unsigned int i, arrayCount = 0; if (ctx->cif.nargs > MAX_STACK_ARGS) { tmpBuffer = alloca_aligned(ctx->cif.nargs * PARAM_SIZE, MIN_ALIGN); } #if defined(USE_RAW) (*env)->GetByteArrayRegion(env, paramBuffer, 0, ctx->rawParameterSize, tmpBuffer + rawAdj); #else if (ctx->cif.nargs > MAX_STACK_ARGS) { ffiArgs = alloca_aligned(ctx->cif.nargs * sizeof(void *), MIN_ALIGN); } for (i = 0; i < ctx->cif.nargs; ++i) { ffiArgs[i] = &tmpBuffer[i * PARAM_SIZE]; } (*env)->GetByteArrayRegion(env, paramBuffer, 0, ctx->cif.nargs * PARAM_SIZE, tmpBuffer); #endif if (objectCount > MAX_STACK_OBJECTS) { arrays = alloca_aligned(objectCount * sizeof(Array), MIN_ALIGN); } initStackAllocator(&alloc); 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: ptr = jffi_getArray(env, object, offset, length, type, &alloc, &arrays[arrayCount]); if (ptr == NULL) { throwException(env, NullPointer, "Could not allocate array"); goto cleanup; } ++arrayCount; break; case com_kenai_jffi_ObjectBuffer_BUFFER: ptr = (*env)->GetDirectBufferAddress(env, object); if (ptr == NULL) { throwException(env, NullPointer, "Could not get direct Buffer address"); goto cleanup; } ptr = ((char *) ptr + offset); break; default: throwException(env, IllegalArgument, "Unsupported object type: %#x", type & com_kenai_jffi_ObjectBuffer_TYPE_MASK); goto cleanup; } #if defined(USE_RAW) *((void **)(tmpBuffer + rawAdj + ctx->rawParamOffsets[idx])) = ptr; #else if (ctx->cif.arg_types[idx]->type == FFI_TYPE_STRUCT) { ffiArgs[idx] = ptr; } else { *((void **) ffiArgs[idx]) = ptr; } #endif } #if defined(USE_RAW) // For struct return values, we need to push a return value address on the parameter stack if (ctx->cif.rtype->type == FFI_TYPE_STRUCT) { *(void **) tmpBuffer = retval; } 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 set_last_error(errno); cleanup: /* Release any array backing memory */ for (i = 0; i < arrayCount; ++i) { if (!arrays[i].stack || arrays[i].mode != JNI_ABORT) { //printf("releasing array=%p\n", arrays[i].result); (*arrays[i].release)(env, &arrays[i]); } } }
void front_or_back(char **argv, int fg_or_not) { int jid = 0; int fg_run = fg_or_not; pid_t pid = 0; pid_t j2pid = 0; if (fbg_argv_ok(argv, &pid, &jid)) { if (pid) { if (selectjob(pid)) { child_block(); restart_job(pid); if (fg_run) { forepid = pid; setpgid(pid, shellpid); child_unblock(); printf("bg ready to fg\n"); while (1) sleep(50); printf("u never see me\n"); return; } else { child_unblock(); return; } } else { fprintf(stderr, "%d: No such process\n", pid); return; } } else { j2pid = j2p(jid); if (selectjob(j2pid)) { child_block(); restart_job(j2pid); if (fg_run) { forepid = j2pid; setpgid(j2pid, shellpid); child_unblock(); printf("bg ready to fg\n"); while (1) sleep(50); printf("u never see me\n"); return; } else { child_unblock(); return; } } else { fprintf(stderr, "%d: No such process\n", j2p(jid)); return; } } } else fprintf(stderr, "usage: %s <%%jid> or %s <pid>\n", argv[0], argv[0]); return; }
JNIEXPORT jlong JNICALL Java_com_kenai_jffi_Foreign_newClosureMagazine(JNIEnv *env, jobject self, jlong ctxAddress, jobject closureMethod, jboolean callWithPrimitiveParameters) { CallContext* ctx = (CallContext *) j2p(ctxAddress); Closure* list = NULL; Magazine* magazine = NULL; caddr_t code = NULL; char errmsg[256]; int i; int trampolineSize, pageSize, nclosures; trampolineSize = roundup(sizeof(ffi_closure), 8); pageSize = jffi_getPageSize(); nclosures = pageSize / trampolineSize; magazine = calloc(1, sizeof(*magazine)); list = calloc(nclosures, sizeof(*list)); code = jffi_allocatePages(1); if (magazine == NULL || list == NULL || code == NULL) { snprintf(errmsg, sizeof(errmsg), "failed to allocate a page. errno=%d (%s)", errno, strerror(errno)); goto error; } // Thread all the closure handles onto a list, and init each one for (i = 0; i < nclosures; ++i) { Closure* closure = &list[i]; closure->magazine = magazine; closure->code = (code + (i * trampolineSize)); if (!closure_prep(&ctx->cif, closure->code, closure, errmsg, sizeof(errmsg))) { goto error; } } if (!jffi_makePagesExecutable(code, 1)) { snprintf(errmsg, sizeof(errmsg), "failed to make page executable. errno=%d (%s)", errno, strerror(errno)); goto error; } magazine->methodID = (*env)->FromReflectedMethod(env, closureMethod); if (magazine->methodID == NULL) { throwException(env, IllegalArgument, "could not obtain reference to closure method"); goto error; } /* Track the allocated page + Closure memory area */ magazine->closures = list; magazine->nextclosure = 0; magazine->nclosures = nclosures; magazine->code = code; magazine->callWithPrimitiveParameters = callWithPrimitiveParameters; (*env)->GetJavaVM(env, &magazine->jvm); return p2j(magazine); error: free(list); free(magazine); if (code != NULL) { jffi_freePages(code, 1); } throwException(env, Runtime, errmsg); return 0L; }
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]); } } }
/* * Class: com_kenai_jffi_Foreign * Method: newStruct * Signature: ([J)J */ JNIEXPORT jlong JNICALL Java_com_kenai_jffi_Foreign_newStruct(JNIEnv* env, jobject self, jlongArray typeArray, jboolean isUnion) { ffi_type* s = NULL; int fieldCount; jlong* fieldTypes; int i; if (typeArray == NULL) { throwException(env, NullPointer, "types array cannot be null"); return 0L; } fieldCount = (*env)->GetArrayLength(env, typeArray); if (fieldCount < 1) { throwException(env, IllegalArgument, "No fields specified"); return 0L; } s = calloc(1, sizeof(*s)); if (s == NULL) { return 0L; } // // Need to terminate the list of field types with a NULL, so allocate 1 extra // s->elements = calloc(fieldCount + 1, sizeof(ffi_type *)); if (s->elements == NULL) { goto error; } // Copy out all the field descriptors fieldTypes = alloca(fieldCount * sizeof(jlong)); (*env)->GetLongArrayRegion(env, typeArray, 0, fieldCount, fieldTypes); s->type = FFI_TYPE_STRUCT; s->size = 0; s->alignment = 0; for (i = 0; i < fieldCount; ++i) { ffi_type* elem = (ffi_type *) j2p(fieldTypes[i]); if (elem == NULL) { throwException(env, IllegalArgument, "Type for field %d is NULL", i); goto error; } if (elem->size == 0) { throwException(env, IllegalArgument, "Type for field %d has size 0", i); goto error; } s->elements[i] = elem; if (!isUnion) { s->size = ALIGN(s->size, elem->alignment) + elem->size; } else { s->size = MAX(s->size, elem->size); } s->alignment = MAX(s->alignment, elem->alignment); //printf("s->size=%d s->alignment=%d\n", s->size, s->alignment); } if (s->size == 0) { throwException(env, Runtime, "Struct size is zero"); goto error; } // Include tail padding s->size = ALIGN(s->size, s->alignment); return p2j(s); error: if (s != NULL) { if (s->elements != NULL) { free(s->elements); } free(s); } return 0L; }