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.
6 #include "IoCFFIFunction.h"
7 #include "IoCFFILibrary.h"
8 #include "IoCFFIDataType.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
);
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
},
40 IoObject_addMethodTable_(self
, methodTable
);
46 IoCFFIFunction
*IoCFFIFunction_rawClone(IoCFFIFunction
*proto
)
48 IoObject
*self
= IoObject_rawClonePrimitive(proto
);
49 IoObject_setDataPointer_(self
, calloc(1, sizeof(IoCFFIFunctionData
)));
53 void IoCFFIFunction_free(IoCFFIFunction
*self
)
58 /* ---------------------------------------------------------------- */
60 IoObject
*IoCFFIFunction_call(IoCFFIFunction
*self
, IoObject
*locals
, IoMessage
*m
)
62 IoCFFILibrary
*library
;
64 void *funPointer
, **funArgVals
, *funRetVal
;
65 ffi_type
**funArgTypes
, *funRetType
;
66 ffi_cif
*funInterface
;
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
);
91 printf("\n\nUh oh. Something went wrong in IoCFFIFunction_call.\n\n");
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
);
115 return returnValAsObj
;