comparison function.c @ 37:d4efcbb06964

Added a new PYM_JSFunction type, PYM_JSContext.define_property(), and PYM_JSContext.new_function(). Also fixed a memory leak.
author Atul Varma <varmaa@toolness.com>
date Thu, 02 Jul 2009 22:42:31 -0700
parents
children 9103afca7386
comparison
equal deleted inserted replaced
36:04a6e9a67ae5 37:d4efcbb06964
1 #include "function.h"
2 #include "utils.h"
3
4 static void
5 PYM_JSFunctionDealloc(PYM_JSFunction *self)
6 {
7 // TODO: What if there's still a reference to the callable in
8 // JS-land?
9 if (self->callable) {
10 Py_DECREF(self->callable);
11 self->callable = NULL;
12 }
13 PYM_JSObjectType.tp_dealloc((PyObject *) self);
14 }
15
16 static JSBool
17 dispatchJSFunctionToPython(JSContext *cx,
18 JSObject *obj,
19 uintN argc,
20 jsval *argv,
21 jsval *rval)
22 {
23 jsval callee = JS_ARGV_CALLEE(argv);
24 jsval jsCallable;
25 if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(callee), 0, &jsCallable)) {
26 JS_ReportError(cx, "JS_GetReservedSlot() failed.");
27 return JS_FALSE;
28 }
29 PyObject *callable = (PyObject *) JSVAL_TO_PRIVATE(jsCallable);
30
31 // TODO: Convert args and 'this' parameter.
32 PyObject *args = PyTuple_New(0);
33 if (args == NULL) {
34 JS_ReportOutOfMemory(cx);
35 return JS_FALSE;
36 }
37
38 PyObject *result = PyObject_Call(callable, args, NULL);
39 if (result == NULL) {
40 // TODO: Get the actual exception.
41 JS_ReportError(cx, "Python function failed.");
42 return JS_FALSE;
43 }
44
45 int error = PYM_pyObjectToJsval(cx, result, rval);
46 Py_DECREF(result);
47
48 if (error) {
49 // TODO: Get the actual exception.
50 JS_ReportError(cx, "Python function failed.");
51 return JS_FALSE;
52 }
53 return JS_TRUE;
54 }
55
56 PYM_JSFunction *
57 PYM_newJSFunction(PYM_JSContextObject *context,
58 PyObject *callable,
59 const char *name)
60 {
61 if (!PyCallable_Check(callable)) {
62 PyErr_SetString(PyExc_TypeError, "Callable must be callable");
63 return NULL;
64 }
65
66 JSFunction *func = JS_NewFunction(context->cx,
67 dispatchJSFunctionToPython, 0,
68 0, NULL, name);
69
70 if (func == NULL) {
71 PyErr_SetString(PYM_error, "JS_DefineFunction() failed");
72 return NULL;
73 }
74
75 JSObject *funcObj = JS_GetFunctionObject(func);
76
77 if (funcObj == NULL) {
78 PyErr_SetString(PYM_error, "JS_GetFunctionObject() failed");
79 return NULL;
80 }
81
82 if (!JS_SetReservedSlot(context->cx, funcObj, 0,
83 PRIVATE_TO_JSVAL(callable))) {
84 PyErr_SetString(PYM_error, "JS_SetReservedSlot() failed");
85 return NULL;
86 }
87
88 PYM_JSFunction *object = PyObject_New(PYM_JSFunction,
89 &PYM_JSFunctionType);
90 if (object == NULL)
91 return NULL;
92
93 object->callable = NULL;
94 if (PYM_newJSObject(context, funcObj,
95 (PYM_JSObject *) object) == NULL)
96 // Note that our object's reference count will have already
97 // been decremented by PYM_newJSObject().
98 return NULL;
99
100 object->callable = callable;
101 Py_INCREF(callable);
102
103 return object;
104 }
105
106 PyTypeObject PYM_JSFunctionType = {
107 PyObject_HEAD_INIT(NULL)
108 0, /*ob_size*/
109 "pymonkey.Function", /*tp_name*/
110 sizeof(PYM_JSFunction), /*tp_basicsize*/
111 0, /*tp_itemsize*/
112 /*tp_dealloc*/
113 (destructor) PYM_JSFunctionDealloc,
114 0, /*tp_print*/
115 0, /*tp_getattr*/
116 0, /*tp_setattr*/
117 0, /*tp_compare*/
118 0, /*tp_repr*/
119 0, /*tp_as_number*/
120 0, /*tp_as_sequence*/
121 0, /*tp_as_mapping*/
122 0, /*tp_hash */
123 0, /*tp_call*/
124 0, /*tp_str*/
125 0, /*tp_getattro*/
126 0, /*tp_setattro*/
127 0, /*tp_as_buffer*/
128 /*tp_flags*/
129 Py_TPFLAGS_DEFAULT,
130 /* tp_doc */
131 "JavaScript Function.",
132 0, /* tp_traverse */
133 0, /* tp_clear */
134 0, /* tp_richcompare */
135 0, /* tp_weaklistoffset */
136 0, /* tp_iter */
137 0, /* tp_iternext */
138 0, /* tp_methods */
139 0, /* tp_members */
140 0, /* tp_getset */
141 0, /* tp_base */
142 0, /* tp_dict */
143 0, /* tp_descr_get */
144 0, /* tp_descr_set */
145 0, /* tp_dictoffset */
146 0, /* tp_init */
147 0, /* tp_alloc */
148 0, /* tp_new */
149 };