1 //metadoc CFunction copyright Steve Dekorte 2002
2 //metadoc CFunction license BSD revised
3 /*metadoc CFunction description
4 A container for a pointer to a C function binding.
5 CFunction's can only be defined from the C side and act
6 like blocks in that when placed in a slot, are called when the
7 slot is activated. The for, if, while and clone methods of the Lobby
8 are examples of CFunctions. CFunctions are useful for implementing
9 methods that require the speed of C or binding to a C library.
11 //metadoc CFunction category Core")
13 #include "IoCFunction.h"
19 #define DATA(self) ((IoCFunctionData *)IoObject_dataPointer(self))
21 IoTag
*IoCFunction_newTag(void *state
)
23 IoTag
*tag
= IoTag_newWithName_("CFunction");
24 IoTag_state_(tag
, state
);
25 IoTag_cloneFunc_(tag
, (IoTagCloneFunc
*)IoCFunction_rawClone
);
26 IoTag_markFunc_(tag
, (IoTagMarkFunc
*)IoCFunction_mark
);
27 IoTag_activateFunc_(tag
, (IoTagActivateFunc
*)IoCFunction_activate
);
28 IoTag_freeFunc_(tag
, (IoTagFreeFunc
*)IoCFunction_free
);
32 IoCFunction
*IoCFunction_proto(void *state
)
34 IoObject
*self
= IoObject_new(state
);
35 IoObject_tag_(self
, IoCFunction_newTag(state
));
37 IoObject_setDataPointer_(self
, io_calloc(1, sizeof(IoCFunctionData
)));
38 DATA(self
)->func
= IoObject_self
;
39 //IoObject_isActivatable_(self, 1);
40 IoState_registerProtoWithFunc_((IoState
*)state
, self
, IoCFunction_proto
);
44 void IoCFunction_protoFinish(void *state
)
46 IoMethodTable methodTable
[] = {
47 {"id", IoCFunction_id
},
48 {"==", IoCFunction_equals
},
49 {"performOn", IoCFunction_performOn
},
50 {"uniqueName", IoCFunction_uniqueName
},
51 {"typeName", IoCFunction_typeName
},
55 IoObject
*self
= IoState_protoWithInitFunction_((IoState
*)state
, IoCFunction_proto
);
56 IoObject_setSlot_to_(self
, IOSYMBOL("type"), IOSYMBOL("CFunction"));
60 IoObject_addMethodTable_(self
, methodTable
);
63 IoCFunction
*IoCFunction_rawClone(IoCFunction
*proto
)
65 IoObject
*self
= IoObject_rawClonePrimitive(proto
);
66 IoObject_setDataPointer_(self
, cpalloc(DATA(proto
), sizeof(IoCFunctionData
)));
67 IoObject_isActivatable_(self
, 1);
71 void IoCFunction_mark(IoCFunction
*self
)
73 if (DATA(self
)->uniqueName
)
75 IoObject_shouldMark(DATA(self
)->uniqueName
);
79 void IoCFunction_free(IoCFunction
*self
)
81 io_free(IoObject_dataPointer(self
));
84 void IoCFunction_print(IoCFunction
*self
)
86 IoCFunctionData
*data
= DATA(self
);
88 printf("CFunction_%p", self
);
89 printf(" %p", (data
->func
));
90 printf(" %s", data
->typeTag
? data
->typeTag
->name
: "?");
91 if (data
->uniqueName
) printf(" %s", CSTRING(data
->uniqueName
));
95 IoCFunction
*IoCFunction_newWithFunctionPointer_tag_name_(void *state
,
100 IoCFunction
*proto
= IoState_protoWithInitFunction_((IoState
*)state
, IoCFunction_proto
);
101 IoCFunction
*self
= IOCLONE(proto
);
102 DATA(self
)->typeTag
= typeTag
;
103 DATA(self
)->func
= func
;
104 DATA(self
)->uniqueName
= IoState_symbolWithCString_((IoState
*)state
, funcName
);
108 IoObject
*IoCFunction_id(IoCFunction
*self
, IoObject
*locals
, IoMessage
*m
)
111 Returns a number containing a unique id for the receiver's internal C function.
114 return IONUMBER(((uintptr_t)self
));
117 IoObject
*IoCFunction_uniqueName(IoCFunction
*self
, IoObject
*locals
, IoMessage
*m
)
119 /*doc CFunction uniqueName
120 Returns the name given to the CFunction.
123 if (DATA(self
)->uniqueName
)
125 return DATA(self
)->uniqueName
;
131 IoObject
*IoCFunction_typeName(IoCFunction
*self
, IoObject
*locals
, IoMessage
*m
)
133 /*doc CFunction typeName
134 Returns the owning type of the CFunction or nil if the CFunction can be called on any object.
137 if (DATA(self
)->typeTag
)
139 return IOSYMBOL(IoTag_name(DATA(self
)->typeTag
));
145 IoObject
*IoCFunction_equals(IoCFunction
*self
, IoObject
*locals
, IoMessage
*m
)
147 /*doc CFunction ==(anObject)
148 Returns self if the argument is a CFunction with the same internal C function pointer.
151 IoObject
*v
= IoMessage_locals_valueArgAt_(m
, locals
, 0);
153 return IOBOOL(self
, ISCFUNCTION(v
) && (DATA(self
)->func
== DATA(v
)->func
));
156 IoObject
*IoCFunction_activate(IoCFunction
*self
, IoObject
*target
, IoObject
*locals
, IoMessage
*m
, IoObject
*slotContext
)
158 IoCFunctionData
*selfData
= DATA(self
);
159 IoTag
*t
= selfData
->typeTag
;
160 //IoObject_waitOnFutureIfNeeded(target); future forward will already deal with this?
163 if (t
&& t
!= IoObject_tag(target
)) // eliminate t check by matching Object tag?
165 char *a
= (char *)IoTag_name(t
);
166 char *b
= (char *)IoTag_name(IoObject_tag(target
));
167 IoState_error_(IOSTATE
, m
, "CFunction defined for type %s but called on type %s", a
, b
);
170 //IoState_pushRetainPool(state);
171 result
= (*(IoUserFunction
*)(selfData
->func
))(target
, locals
, m
);
172 //IoState_popRetainPoolExceptFor_(state, result);
176 IoObject
*IoCFunction_performOn(IoCFunction
*self
, IoObject
*locals
, IoMessage
*m
)
178 /*doc CFunction performOn(target, blockLocals, optionalMessage, optionalContext)
179 Activates the CFunctions with the supplied settings.
182 IoObject
*bTarget
= IoMessage_locals_valueArgAt_(m
, locals
, 0);
183 IoObject
*bLocals
= locals
;
184 IoObject
*bMessage
= m
;
185 IoObject
*bContext
= bTarget
;
186 int argCount
= IoMessage_argCount(m
);
190 bLocals
= IoMessage_locals_valueArgAt_(m
, locals
, 1);
195 bMessage
= IoMessage_locals_valueArgAt_(m
, locals
, 2);
200 bContext
= IoMessage_locals_valueArgAt_(m
, locals
, 3);
203 return IoCFunction_activate(self
, bTarget
, bLocals
, bMessage
, bContext
);