Updating built in Io code to use += instead of x = x + y
[io/quag.git] / addons / CFFI / source / IoCFFIFunction.c
blobf8fc730cd811f66698b60dcc5662796818633abb
1 /* CFFI - An Io interface to C
2 Copyright (c) 2006 Trevor Fancher. All rights reserved.
3 All code licensed under the New BSD license.
4 */
6 #include "IoCFFIFunction.h"
7 #include "IoCFFILibrary.h"
8 #include "IoCFFIDataType.h"
9 #include "IoState.h"
10 #include "IoNumber.h"
11 #include "IoList.h"
12 #include "List.h"
13 #include <ffi.h>
15 #define DATA(self) ((IoCFFIFunctionData *)(IoObject_dataPointer(self)))
17 IoTag *IoCFFIFunction_newTag(void *state)
19 IoTag *tag = IoTag_newWithName_("Function");
20 IoTag_state_(tag, state);
21 IoTag_freeFunc_(tag, (IoTagFreeFunc *)IoCFFIFunction_free);
22 IoTag_cloneFunc_(tag, (IoTagCloneFunc *)IoCFFIFunction_rawClone);
23 return tag;
26 IoCFFIFunction *IoCFFIFunction_proto(void *state)
28 IoObject *self = IoObject_new(state);
29 IoObject_tag_(self, IoCFFIFunction_newTag(state));
31 IoObject_setDataPointer_(self, calloc(1, sizeof(IoCFFIFunctionData)));
33 IoState_registerProtoWithFunc_(state, self, IoCFFIFunction_proto);
36 IoMethodTable methodTable[] = {
37 {"call", IoCFFIFunction_call},
38 {NULL, NULL},
40 IoObject_addMethodTable_(self, methodTable);
43 return self;
46 IoCFFIFunction *IoCFFIFunction_rawClone(IoCFFIFunction *proto)
48 IoObject *self = IoObject_rawClonePrimitive(proto);
49 IoObject_setDataPointer_(self, calloc(1, sizeof(IoCFFIFunctionData)));
50 return self;
53 void IoCFFIFunction_free(IoCFFIFunction *self)
55 free(DATA(self));
58 /* ---------------------------------------------------------------- */
60 IoObject *IoCFFIFunction_call(IoCFFIFunction *self, IoObject *locals, IoMessage *m)
62 IoCFFILibrary *library;
63 const char *funName;
64 void *funPointer, **funArgVals, *funRetVal;
65 ffi_type **funArgTypes, *funRetType;
66 ffi_cif *funInterface;
67 int funArgCount, i;
68 ffi_status status;
69 IoObject *returnValAsObj, *funRetTypeObject, *o;
70 List *funArgTypeObjects;
72 library = IoObject_getSlot_(self, IOSYMBOL("library"));
73 funInterface = &(DATA(self)->interface);
74 funName = CSTRING(IoObject_getSlot_(self, IOSYMBOL("name")));
75 funPointer = IoCFFILibrary_rawGetFuctionPointer_(library, funName);
76 funArgTypeObjects = IoList_rawList(IoObject_getSlot_(self, IOSYMBOL("argumentTypes")));
77 funRetTypeObject = IoObject_getSlot_(self, IOSYMBOL("returnType"));
79 funArgCount = (int)List_size(funArgTypeObjects);
80 funArgTypes = calloc(funArgCount, sizeof(ffi_type *));
81 for (i = 0; i < funArgCount; i++)
83 o = List_at_(funArgTypeObjects, i);
84 funArgTypes[i] = IoCFFIDataType_ffiType(o);
86 funRetType = IoCFFIDataType_ffiType(funRetTypeObject);
88 status = ffi_prep_cif(funInterface, FFI_DEFAULT_ABI, funArgCount, funRetType, funArgTypes);
89 if (status != FFI_OK)
91 printf("\n\nUh oh. Something went wrong in IoCFFIFunction_call.\n\n");
92 free(funArgTypes);
93 return IONIL(self);
96 funArgVals = calloc(funArgCount, sizeof(void *));
97 funRetVal = calloc(1, funRetType->size);
98 IoState_pushCollectorPause(IOSTATE);
100 for (i = 0; i < funArgCount; i++)
102 o = IoMessage_locals_valueArgAt_(m, locals, i);
103 funArgVals[i] = IoCFFIDataType_ValuePointerFromObject_(o);
106 ffi_call(funInterface, funPointer, funRetVal, funArgVals);
107 returnValAsObj = IoCFFIDataType_objectFromData_(funRetTypeObject, funRetVal);
109 IoState_popCollectorPause(IOSTATE);
111 free(funArgTypes);
112 free(funArgVals);
113 free(funRetVal);
115 return returnValAsObj;