11#include <Python.h>
22
3+ #include "third-party/quickjs.h"
4+
35static PyObject * test (PyObject * self , PyObject * args ) {
46 return Py_BuildValue ("i" , 42 );
57}
68
79struct module_state {};
810
11+ typedef struct {
12+ PyObject_HEAD JSRuntime * runtime ;
13+ JSContext * context ;
14+ } ContextData ;
15+
16+ static PyObject * context_new (PyTypeObject * type , PyObject * args , PyObject * kwds ) {
17+ ContextData * self ;
18+ self = (ContextData * )type -> tp_alloc (type , 0 );
19+ if (self != NULL ) {
20+ self -> runtime = JS_NewRuntime ();
21+ self -> context = JS_NewContext (self -> runtime );
22+ }
23+ return (PyObject * )self ;
24+ }
25+
26+ static void context_dealloc (ContextData * self ) {
27+ JS_FreeContext (self -> context );
28+ JS_FreeRuntime (self -> runtime );
29+ Py_TYPE (self )-> tp_free ((PyObject * )self );
30+ }
31+
32+ static PyObject * context_eval (ContextData * self , PyObject * args ) {
33+ const char * code ;
34+ if (!PyArg_ParseTuple (args , "s" , & code )) {
35+ return NULL ;
36+ }
37+ JSValue value = JS_Eval (self -> context , code , strlen (code ), "<input>" , JS_EVAL_TYPE_GLOBAL );
38+ int tag = JS_VALUE_GET_TAG (value );
39+ PyObject * return_value = NULL ;
40+
41+ if (tag == JS_TAG_INT ) {
42+ return_value = Py_BuildValue ("i" , JS_VALUE_GET_INT (value ));
43+ } else if (tag == JS_TAG_BOOL ) {
44+ return_value = Py_BuildValue ("O" , JS_VALUE_GET_BOOL (value ) ? Py_True : Py_False );
45+ } else if (tag == JS_TAG_NULL ) {
46+ // None
47+ } else if (tag == JS_TAG_UNDEFINED ) {
48+ // None
49+ } else if (tag == JS_TAG_UNINITIALIZED ) {
50+ // None
51+ } else if (tag == JS_TAG_EXCEPTION ) {
52+ // TODO: Raise exception.
53+ } else if (tag == JS_TAG_FLOAT64 ) {
54+ return_value = Py_BuildValue ("d" , JS_VALUE_GET_FLOAT64 (value ));
55+ } else if (tag == JS_TAG_STRING ) {
56+ const char * cstring = JS_ToCString (self -> context , value );
57+ return_value = Py_BuildValue ("s" , cstring );
58+ JS_FreeCString (self -> context , cstring );
59+ } else {
60+ // TODO: Raise exception.
61+ }
62+
63+ JS_FreeValue (self -> context , value );
64+ if (return_value == NULL ) {
65+ Py_RETURN_NONE ;
66+ }
67+ return return_value ;
68+ }
69+
70+ static PyMethodDef context_methods [] = {
71+ {"eval" , (PyCFunction )context_eval , METH_VARARGS , "Evaluates a Javascript string." },
72+ {NULL } /* Sentinel */
73+ };
74+
75+ static PyTypeObject Context = {PyVarObject_HEAD_INIT (NULL , 0 ).tp_name = "_quickjs.Context" ,
76+ .tp_doc = "Quickjs context" ,
77+ .tp_basicsize = sizeof (ContextData ),
78+ .tp_itemsize = 0 ,
79+ .tp_flags = Py_TPFLAGS_DEFAULT ,
80+ .tp_new = context_new ,
81+ .tp_dealloc = (destructor )context_dealloc ,
82+ .tp_methods = context_methods };
83+
984static PyMethodDef myextension_methods [] = {{"test" , (PyCFunction )test , METH_NOARGS , NULL },
1085 {NULL , NULL }};
1186
@@ -20,5 +95,16 @@ static struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT,
2095 NULL };
2196
2297PyMODINIT_FUNC PyInit__quickjs (void ) {
23- return PyModule_Create (& moduledef );
98+ if (PyType_Ready (& Context ) < 0 ) {
99+ return NULL ;
100+ }
101+
102+ PyObject * module = PyModule_Create (& moduledef );
103+ if (module == NULL ) {
104+ return NULL ;
105+ }
106+
107+ Py_INCREF (& Context );
108+ PyModule_AddObject (module , "Context" , (PyObject * )& Context );
109+ return module ;
24110}
0 commit comments