Mercurial > pymonkey
view pymonkey.c @ 7:0d0ce6415b66
Added support for unicode strings.
author | Atul Varma <varmaa@toolness.com> |
---|---|
date | Sun, 28 Jun 2009 13:09:39 -0700 |
parents | 42f57789f84f |
children | 6647870380cc |
line wrap: on
line source
#include "jsapi.h" #include <Python/Python.h> static JSClass PYM_jsGlobalClass = { "PymonkeyGlobal", JSCLASS_GLOBAL_FLAGS, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, JSCLASS_NO_OPTIONAL_MEMBERS }; static PyObject *PYM_error; static PyObject * PYM_jsvalToPyObject(jsval value) { if (JSVAL_IS_INT(value)) return PyInt_FromLong(JSVAL_TO_INT(value)); if (JSVAL_IS_DOUBLE(value)) { jsdouble *doubleRef = JSVAL_TO_DOUBLE(value); return PyFloat_FromDouble(*doubleRef); } if (value == JSVAL_FALSE) Py_RETURN_FALSE; if (value == JSVAL_TRUE) Py_RETURN_TRUE; if (JSVAL_IS_NULL(value)) Py_RETURN_NONE; if (JSVAL_IS_STRING(value) && JS_CStringsAreUTF8()) { // TODO: What to do if C strings aren't UTF-8? The jschar * // type isn't actually UTF-16, it's just "UTF-16-ish", so // there doesn't seem to be any other lossless way of // transferring the string other than perhaps by transmitting // its JSON representation. JSString *str = JSVAL_TO_STRING(value); const char *bytes = JS_GetStringBytes(str); const char *errors; return PyUnicode_DecodeUTF8(bytes, strlen(bytes), errors); } // TODO: Support more types. PyErr_SetString(PyExc_NotImplementedError, "Data type conversion not implemented."); } static PyObject * PYM_evaluate(PyObject *self, PyObject *args) { const char *source; int sourceLen; const char *filename; int lineNo; if (!PyArg_ParseTuple(args, "s#si", &source, &sourceLen, &filename, &lineNo)) return NULL; if (!JS_CStringsAreUTF8()) JS_SetCStringsAreUTF8(); JSRuntime *rt = JS_NewRuntime(8L * 1024L * 1024L); if (rt == NULL) { PyErr_SetString(PYM_error, "JS_NewRuntime() failed"); return NULL; } JSContext *cx = JS_NewContext(rt, 8192); if (cx == NULL) { PyErr_SetString(PYM_error, "JS_NewContext() failed"); JS_DestroyRuntime(rt); } JS_SetOptions(cx, JSOPTION_VAROBJFIX); JS_SetVersion(cx, JSVERSION_LATEST); JS_BeginRequest(cx); JSObject *global = JS_NewObject(cx, &PYM_jsGlobalClass, NULL, NULL); if (global == NULL) { PyErr_SetString(PYM_error, "JS_NewObject() failed"); JS_EndRequest(cx); JS_DestroyContext(cx); JS_DestroyRuntime(rt); return NULL; } if (!JS_InitStandardClasses(cx, global)) { PyErr_SetString(PYM_error, "JS_InitStandardClasses() failed"); JS_EndRequest(cx); JS_DestroyContext(cx); JS_DestroyRuntime(rt); return NULL; } jsval rval; if (!JS_EvaluateScript(cx, global, source, sourceLen, filename, lineNo, &rval)) { // TODO: Actually get the error that was raised. PyErr_SetString(PYM_error, "Script failed"); JS_EndRequest(cx); JS_DestroyContext(cx); JS_DestroyRuntime(rt); return NULL; } PyObject *pyRval = PYM_jsvalToPyObject(rval); JS_EndRequest(cx); JS_DestroyContext(cx); JS_DestroyRuntime(rt); return pyRval; } static PyMethodDef PYM_methods[] = { {"evaluate", PYM_evaluate, METH_VARARGS, "Evaluate the given JavaScript code, using the given filename " "and line number information."}, {NULL, NULL, 0, NULL} }; PyMODINIT_FUNC initpymonkey(void) { PyObject *module; module = Py_InitModule("pymonkey", PYM_methods); if (module == NULL) return; PYM_error = PyErr_NewException("pymonkey.error", NULL, NULL); Py_INCREF(PYM_error); PyModule_AddObject(module, "error", PYM_error); }