IoObject *IoCFFIFunction_call(IoCFFIFunction *self, IoObject *locals, IoMessage *m) { IoCFFILibrary *library; const char *funName; void *funPointer, **funArgVals, *funRetVal; ffi_type **funArgTypes, *funRetType; ffi_cif *funInterface; int funArgCount, i; ffi_status status; IoObject *returnValAsObj, *funRetTypeObject, *o; List *funArgTypeObjects; library = IoObject_getSlot_(self, IOSYMBOL("library")); funInterface = &(DATA(self)->interface); funName = CSTRING(IoObject_getSlot_(self, IOSYMBOL("name"))); funPointer = IoCFFILibrary_rawGetFuctionPointer_(library, funName); funArgTypeObjects = IoList_rawList(IoObject_getSlot_(self, IOSYMBOL("argumentTypes"))); funRetTypeObject = IoObject_getSlot_(self, IOSYMBOL("returnType")); funArgCount = (int)List_size(funArgTypeObjects); funArgTypes = calloc(funArgCount, sizeof(ffi_type *)); for (i = 0; i < funArgCount; i++) { o = List_at_(funArgTypeObjects, i); funArgTypes[i] = IoCFFIDataType_ffiType(o); } funRetType = IoCFFIDataType_ffiType(funRetTypeObject); status = ffi_prep_cif(funInterface, FFI_DEFAULT_ABI, funArgCount, funRetType, funArgTypes); if (status != FFI_OK) { printf("\n\nUh oh. Something went wrong in IoCFFIFunction_call.\n\n"); free(funArgTypes); return IONIL(self); } funArgVals = calloc(funArgCount, sizeof(void *)); funRetVal = calloc(1, funRetType->size); IoState_pushCollectorPause(IOSTATE); { for (i = 0; i < funArgCount; i++) { o = IoMessage_locals_valueArgAt_(m, locals, i); funArgVals[i] = IoCFFIDataType_ValuePointerFromObject_(o); } ffi_call(funInterface, funPointer, funRetVal, funArgVals); returnValAsObj = IoCFFIDataType_objectFromData_(funRetTypeObject, funRetVal); } IoState_popCollectorPause(IOSTATE); free(funArgTypes); free(funArgVals); free(funRetVal); return returnValAsObj; }
IoCFFIArray *IoCFFIArray_with(IoCFFIArray *self, IoObject *locals, IoMessage *m) { IoCFFIDataType *type; int size, i; ffi_type *item_type; IoCFFIArray *o = IOCLONE(self); IoState_on_doCString_withLabel_(IoObject_state(o), o, "init", "IoCFFIArray_with"); type = IOCLONE(IoMessage_locals_valueArgAt_(m, locals, 0)); IoObject_setSlot_to_(o, IOSYMBOL("arrayType"), type); size = IoMessage_locals_intArgAt_(m, locals, 1); DATA(o)->arraySize = size; item_type = IoCFFIDataType_ffiType(type); DATA(o)->itemSize = item_type->size; // Fake libffi to think we are a Struct DATA(o)->ffiType.size = 0; DATA(o)->ffiType.alignment = 0; DATA(o)->ffiType.type = FFI_TYPE_STRUCT; DATA(o)->ffiType.elements = io_calloc(size + 1, sizeof(ffi_type *)); DATA(o)->needToFreeFFIType = 1; for ( i = 0 ; i < size ; i++ ) { DATA(o)->ffiType.elements[i] = item_type; } DATA(o)->ffiType.elements[size] = NULL; ffi_cif cif; ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0, &(DATA(o)->ffiType), NULL); return o; }
IoObject *IoCFFIPointer_atPut(IoCFFIPointer *self, IoObject *locals, IoMessage *m) { int pos; IoObject *value, *pointedToType, *d; char *ptr; //TODO comprobar overrun y coincidencia de tipos pos = CNUMBER(IoMessage_locals_numberArgAt_(m, locals, 0)); value = IoMessage_locals_valueArgAt_(m, locals, 1); pointedToType = IoObject_getSlot_(self, IOSYMBOL("pointedToType")); ptr = ((char *)*(DATA(self)->valuePointer)) + (IoCFFIDataType_ffiType(pointedToType)->size * pos); d = IOCLONE(pointedToType); IoCFFIDataType_rawSetValue(d, value); memcpy(ptr, (void *)IoCFFIDataType_ValuePointerFromObject_(NULL, d), IoCFFIDataType_ffiType(pointedToType)->size); return self; }
IoObject *IoCFFIPointer_at(IoCFFIPointer *self, IoObject *locals, IoMessage *m) { int pos; IoObject *pointedToType; char *ptr; pos = CNUMBER(IoMessage_locals_numberArgAt_(m, locals, 0)); pointedToType = IoObject_getSlot_(self, IOSYMBOL("pointedToType")); ptr = ((char *)*(DATA(self)->valuePointer)) + (IoCFFIDataType_ffiType(pointedToType)->size * pos); return IoCFFIDataType_objectFromData_(pointedToType, (void *)ptr); }