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 *)¶ms,
+ (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)
{