ext/pycall/pycall.c in pycall-1.0.3 vs ext/pycall/pycall.c in pycall-1.1.0.rc1

- old
+ new

@@ -1,6 +1,7 @@ #include "pycall_internal.h" +#include "pycall.h" #include <ruby/encoding.h> #include <stdarg.h> VALUE pycall_mPyCall; @@ -141,10 +142,16 @@ PyObject *pyobj; TypedData_Get_Struct(obj, PyObject, &pycall_pyptr_data_type, pyobj); return pyobj; } +PyObject * +pycall_pyptr_get_pyobj_ptr(VALUE pyptr) +{ + return get_pyobj_ptr(pyptr); +} + static inline PyObject* try_get_pyobj_ptr(VALUE obj) { if (!is_pycall_pyptr(obj)) return NULL; return (PyObject*)DATA_PTR(obj); @@ -725,11 +732,10 @@ return pycall_pyobject_to_ruby(res); } static int is_pyobject_wrapper(VALUE obj); -static PyObject * pycall_pyobject_wrapper_get_pyobj_ptr(VALUE obj); VALUE pycall_getattr_default(VALUE obj, char const *name, VALUE default_value) { PyObject *pyobj, *res; @@ -856,10 +862,46 @@ return ST_STOP; } return ST_CONTINUE; } +static void +pycall_interrupt_python_thread(void *ptr) +{ + Py_API(PyErr_SetInterrupt)(); +} + +struct call_pyobject_call_params { + PyObject *pycallable; + PyObject *args; + PyObject *kwargs; +}; + +PyObject * +call_pyobject_call(struct call_pyobject_call_params *params) +{ + PyObject *res; + res = Py_API(PyObject_Call)(params->pycallable, params->args, params->kwargs); /* New reference */ + return res; +} + +PyObject * +pyobject_call_without_gvl(PyObject *pycallable, PyObject *args, PyObject *kwargs) +{ + PyObject *res; + struct call_pyobject_call_params params; + params.pycallable = pycallable; + params.args = args; + params.kwargs = kwargs; + + res = (PyObject *)rb_thread_call_without_gvl( + (void * (*)(void *))call_pyobject_call, (void *)&params, + (rb_unblock_function_t *)pycall_interrupt_python_thread, NULL); + + return res; +} + static VALUE pycall_call_python_callable(PyObject *pycallable, int argc, VALUE *argv) { PyObject *args, *res; PyObject *kwargs = NULL; @@ -903,11 +945,11 @@ pycall_pyerror_fetch_and_raise("PyDict_SetItemString in pycall_extract_kwargs_from_ruby_hash"); } } } - res = Py_API(PyObject_Call)(pycallable, args, kwargs); /* New reference */ + res = pyobject_call_without_gvl(pycallable, args, kwargs); /* New reference */ if (!res) { pycall_pyerror_fetch_and_raise("PyObject_Call in pycall_call_python_callable"); } obj = pycall_pyobject_to_ruby(res); pycall_Py_DecRef(res); @@ -1211,11 +1253,11 @@ } return rb_funcall(obj, rb_intern("__pyptr__"), 0); } -static PyObject * +PyObject * pycall_pyobject_wrapper_get_pyobj_ptr(VALUE obj) { VALUE pyptr = pycall_pyobject_wrapper_get_pyptr(obj); return get_pyobj_ptr(pyptr); } @@ -1945,10 +1987,14 @@ static char const *argv[1] = { "" }; Py_API(Py_InitializeEx)(0); Py_API(PySys_SetArgvEx)(0, (char **)argv, 0); + if (!Py_API(PyEval_ThreadsInitialized)()) { + Py_API(PyEval_InitThreads)(); + } + /* check the availability of stackless extension */ python_has_stackless_extension = (Py_API(PyImport_ImportModule)("stackless") != NULL); if (!python_has_stackless_extension) { Py_API(PyErr_Clear)(); } @@ -2076,9 +2122,10 @@ rb_define_const(mPyCall, "Tuple", cTuple); rb_funcall(cTuple, rb_intern("register_python_type_mapping"), 0); rb_define_singleton_method(cTuple, "new", pycall_tuple_s_new, -1); rb_define_method(cTuple, "length", pycall_tuple_length, 0); rb_define_method(cTuple, "to_a", pycall_tuple_to_a, 0); + rb_define_alias(cTuple, "to_ary", "to_a"); } void Init_pycall(void) {