Skip to content

Commit

Permalink
Add ability to bind ret value in python to py-call-function
Browse files Browse the repository at this point in the history
  • Loading branch information
813gan committed Aug 13, 2024
1 parent 4a34dec commit d767fdf
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 11 deletions.
10 changes: 6 additions & 4 deletions emacspy.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ cdef extern from "subinterpreter.c":
void make_interpreter(char*)
object run_string(char*, char*, object)
object call_method(char*, object, object, object, object, object)
object call_function(object, object, char*)
object call_function(char*, object, object, object)
object import_module(object, object, char*)
object get_global_variable(object, char*)
object get_object_attr(char*, object, object, object)
Expand Down Expand Up @@ -344,10 +344,12 @@ def init():
return ret

@defun('py-call-function')
def call_function_python(interpreter_name, function_name, *args):
def call_function_python(interpreter_name, function_name, target_name='', *args):
if target_name:
target_name = target_name.to_python_type()
args_py = tuple((arg.to_python_type() for arg in args))
ret = call_function(function_name.to_python_type(), args_py, \
str_elisp2c(interpreter_name))
ret = call_function(str_elisp2c(interpreter_name), function_name.to_python_type(), \
target_name, args_py)
if isinstance(ret, BaseException):
raise ret
return ret
Expand Down
18 changes: 15 additions & 3 deletions subinterpreter.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,16 +200,18 @@ PyObject *call_method(char *interpreter_name, PyObject *obj_name, PyObject *meth
}
}

PyObject* call_function (PyObject *callable_name, PyObject *args_pylist, char *interpreter_name) {
PyObject* call_function (char *interpreter_name, PyObject *callable_name, \
PyObject *target_name, PyObject *args_pylist) {
struct interpr *sub_interpreter = get_interpreter(interpreter_name);
PyGILState_STATE gil = PyGILState_Ensure();
PyThreadState *orig_tstate = PyThreadState_Get();
PyThreadState_Swap(sub_interpreter->python_interpreter);

PyObject *global_dict = PyModule_GetDict(sub_interpreter->main_module);
PyObject *callable = PyObject_GetItem(global_dict, callable_name); // New reference
PyObject *exception = NULL;
PyObject *ret = NULL;
PyObject *obj = NULL;
PyObject *exception = NULL;

if (NULL == callable) {
PyObject *builtins_name = PyUnicode_FromString("__builtins__");
Expand All @@ -223,8 +225,18 @@ PyObject* call_function (PyObject *callable_name, PyObject *args_pylist, char *i

assert(callable);

ret = PyObject_Call(callable, args_pylist, NULL);
obj = PyObject_Call(callable, args_pylist, NULL);
exception = PyErr_GetRaisedException();
if (exception)
goto finish;

if (PyUnicode_GetLength(target_name) > 0) {
ret = Py_True;
PyObject_SetItem(global_dict, target_name, obj);
exception = PyErr_GetRaisedException();
} else {
ret = obj;
}

finish:
Py_XDECREF(callable);
Expand Down
9 changes: 5 additions & 4 deletions tests/test.el
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@
)

(ert-deftest ert-test-emacspy-py-call-function ()
(should (eq 3 (py-call-function "test" "len" "123")))
(should-error (py-call-function "test" "NON-EXISTING-FUNCTION" "123")
:type 'python-exception)
)
(should (eq 3 (py-call-function "test" "len" nil "123")))
(should (py-call-function "test" "len" "call_function_test_var" "123"))
(should (eq 3 (py-get-global-variable "test" "call_function_test_var")))
(should-error (py-call-function "test" "NON-EXISTING-FUNCTION" nil "123")
:type 'python-exception) )

(ert-deftest ert-test-emacspy-py-get-object-attr ()
(should (string= "0123456789" (py-get-object-attr "test" "string" "digits")))
Expand Down

0 comments on commit d767fdf

Please sign in to comment.