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_at(IoCFFIArray *self, IoObject *locals, IoMessage *m) { int pos; char *ptr; //TODO check limits pos = CNUMBER(IoMessage_locals_numberArgAt_(m, locals, 0)); ptr = ((char *)DATA(self)->buffer) + (DATA(self)->itemSize * pos); return IoCFFIDataType_objectFromData_(IoObject_getSlot_(self, IOSYMBOL("arrayType")), (void *)ptr); }
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); }
IoCFFIArray *IoCFFIArray_at(IoCFFIArray *self, IoObject *locals, IoMessage *m) { int pos; char *ptr; pos = CNUMBER(IoMessage_locals_numberArgAt_(m, locals, 0)); if ( pos >= DATA(self)->arraySize ) { IoState_error_(IOSTATE, m, "index out of bounds"); return IONIL(self); } ptr = ((char *)DATA(self)->buffer) + (DATA(self)->itemSize * pos); return IoCFFIDataType_objectFromData_(IoObject_getSlot_(self, IOSYMBOL("arrayType")), (void *)ptr); }
IoObject *IoCFFIPointer_value(IoCFFIPointer *self, IoObject *locals, IoMessage *m) { IoObject *pointedToType; IoCFFIPointer *pointer; char *typeString, *cp, c; if (*(DATA(self)->valuePointer) == NULL) { //IoState_error_(IOSTATE, m, "attempt to dereference NULL pointer"); return IONIL(self); } typeString = CSTRING(IoState_on_doCString_withLabel_(IOSTATE, self, "typeString", "IoCFFIPointer_value")); pointedToType = IoObject_getSlot_(self, IOSYMBOL("pointedToType")); if (ISCFFIPointer(pointedToType)) { // we are a pointer to a pointer, so return a new Pointer // that points to the address of our ptr dereferenced cp = strrchr(typeString, '^'); switch (c = *(++cp)) { #define IoCFFIPointer_value_SET_DATA_PTR(cType) \ pointer = IOCLONE(IoCFFIPointer_ToType_(IoObject_getSlot_(pointedToType, IOSYMBOL("pointedToType")))); \ *(DATA(pointer)->valuePointer) = *((cType **)(*(DATA(self)->valuePointer))); break //DATA(pointer)->ptr = *((cType **)(DATA(self)->ptr)); break case 'c': case 'b': IoCFFIPointer_value_SET_DATA_PTR(char); case 'C': case 'B': IoCFFIPointer_value_SET_DATA_PTR(unsigned char); case 's': IoCFFIPointer_value_SET_DATA_PTR(short); case 'S': IoCFFIPointer_value_SET_DATA_PTR(unsigned short); case 'i': IoCFFIPointer_value_SET_DATA_PTR(int); case 'I': IoCFFIPointer_value_SET_DATA_PTR(unsigned int); case 'l': IoCFFIPointer_value_SET_DATA_PTR(long); case 'L': IoCFFIPointer_value_SET_DATA_PTR(unsigned long); case 'f': IoCFFIPointer_value_SET_DATA_PTR(float); case 'd': IoCFFIPointer_value_SET_DATA_PTR(double); case '*': IoCFFIPointer_value_SET_DATA_PTR(char *); case '{': case '(': case '&': case '[': case 'v': IoCFFIPointer_value_SET_DATA_PTR(void); #undef IoCFFIPointer_value_SET_DATA_PTR //case 'v': // IoState_error_(IOSTATE, m, "attempt to dereference a void pointer"); // return IONIL(self); default: IoState_error_(IOSTATE, m, "unknown character '%c' in Pointer typeString", c); return IONIL(self); } return pointer; } else if(ISCFFIDataType(pointedToType) || ISCFFIStructure(pointedToType) || ISCFFIFunction(pointedToType) || ISCFFIArray(pointedToType)) { return IoCFFIDataType_objectFromData_(pointedToType, *(DATA(self)->valuePointer)); } else { IoState_error_(IOSTATE, m, "attempt to dereference Pointer object whose pointedToType is unknown."); return IONIL(self); } }