diff options
author | Johan Dahlin <johan@gnome.org> | 2008-07-20 10:43:41 +0000 |
---|---|---|
committer | Johan Dahlin <johan@src.gnome.org> | 2008-07-20 10:43:41 +0000 |
commit | 6628e24baebc6dd40f9e76d10391ea5c06d3398a (patch) | |
tree | 68b587325b10d5616381c508609702027db8ba74 /glib/pygspawn.c | |
parent | af2dfa166520a243ea05ff7d4bd5a1fa103d8e0b (diff) | |
download | pygobject-6628e24baebc6dd40f9e76d10391ea5c06d3398a.tar.gz pygobject-6628e24baebc6dd40f9e76d10391ea5c06d3398a.tar.xz pygobject-6628e24baebc6dd40f9e76d10391ea5c06d3398a.zip |
Add glib bindings, currently not installed or used. Add some internal API
2008-07-20 Johan Dahlin <johan@gnome.org>
* Makefile.am:
* configure.ac:
* glib/Makefile.am:
* glib/__init__.py:
* glib/glibmodule.c (pyg_destroy_notify), (get_handler_priority),
(pyg_handler_marshal), (pyg_idle_add), (pyg_timeout_add),
(pyg_timeout_add_seconds), (iowatch_marshal), (pyg_io_add_watch),
(pyg_source_remove), (pyg_main_context_default),
(child_watch_func), (child_watch_dnotify), (pyg_child_watch_add),
(pyg_markup_escape_text), (pyg_get_current_time), (pyg_main_depth),
(pyg_filename_display_name), (pyg_filename_display_basename),
(pyg_filename_from_utf8), (pyg_get_application_name),
(pyg_set_application_name), (pyg_get_prgname), (pyg_set_prgname),
(pyg_register_api), (pyg_register_error),
(pyg_register_version_tuples), (init_glib):
* glib/pyglib-private.h:
* glib/pyglib.c (pyglib_init), (pyglib_init_internal),
(pyglib_gil_state_ensure), (pyglib_gil_state_release),
(pyglib_enable_threads), (pyglib_gil_state_ensure_py23),
(pyglib_gil_state_release_py23), (pyglib_error_check):
* glib/pyglib.h:
* glib/pygspawn.c (pyg_pid_close), (pyg_pid_free),
(pyg_pid_tp_init), (pyg_pid_new), (_pyg_spawn_async_callback),
(pyglib_spawn_async), (pyg_spawn_register_types):
* glib/pygspawn.h:
Add glib bindings, currently not installed or used.
Add some internal API and move over a couple of functions
from the gobject module. Still very much a work in progress.
svn path=/trunk/; revision=839
Diffstat (limited to 'glib/pygspawn.c')
-rw-r--r-- | glib/pygspawn.c | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/glib/pygspawn.c b/glib/pygspawn.c new file mode 100644 index 0000000..08c40aa --- /dev/null +++ b/glib/pygspawn.c @@ -0,0 +1,297 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * pyglib - Python bindings for GLib toolkit. + * Copyright (C) 1998-2003 James Henstridge + * 2004-2008 Johan Dahlin + * + * pygspawn.c: wrapper for the glib library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include <Python.h> +#include <glib/gspawn.h> + +#include "pyglib.h" +#include "pyglib-private.h" + +struct _PyGChildSetupData { + PyObject *func; + PyObject *data; +}; + +static PyObject * +pyg_pid_close(PyIntObject *self, PyObject *args, PyObject *kwargs) +{ + g_spawn_close_pid((GPid) self->ob_ival); + Py_INCREF(Py_None); + return Py_None; +} + +static PyMethodDef pyg_pid_methods[] = { + { "close", (PyCFunction)pyg_pid_close, METH_NOARGS }, + { NULL, NULL, 0 } +}; + +static void +pyg_pid_free(PyIntObject *gpid) +{ + g_spawn_close_pid((GPid) gpid->ob_ival); + PyInt_Type.tp_free((void *) gpid); +} + +static int +pyg_pid_tp_init(PyObject *self, PyObject *args, PyObject *kwargs) +{ + PyErr_SetString(PyExc_TypeError, "glib.Pid cannot be manually instantiated"); + return -1; +} + +static PyTypeObject PyGPid_Type = { + PyObject_HEAD_INIT(NULL) + 0, + "glib.Pid", + sizeof(PyIntObject), + 0, + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + pyg_pid_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + pyg_pid_tp_init, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + (freefunc)pyg_pid_free, /* tp_free */ + 0, /* tp_is_gc */ +}; + +PyObject * +pyg_pid_new(GPid pid) +{ + PyIntObject *pygpid; + pygpid = PyObject_NEW(PyIntObject, &PyGPid_Type); + + pygpid->ob_ival = pid; + return (PyObject *) pygpid; +} + +static void +_pyg_spawn_async_callback(gpointer user_data) +{ + struct _PyGChildSetupData *data; + PyObject *retval; + PyGILState_STATE gil; + + data = (struct _PyGChildSetupData *) user_data; + gil = pyglib_gil_state_ensure(); + if (data->data) + retval = PyObject_CallFunction(data->func, "O", data->data); + else + retval = PyObject_CallFunction(data->func, NULL); + if (retval) + Py_DECREF(retval); + else + PyErr_Print(); + Py_DECREF(data->func); + Py_XDECREF(data->data); + g_free(data); + pyglib_gil_state_release(gil); +} + +PyObject * +pyglib_spawn_async(PyObject *object, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "argv", "envp", "working_directory", "flags", + "child_setup", "user_data", "standard_input", + "standard_output", "standard_error", NULL }; + PyObject *pyargv, *pyenvp = NULL; + char **argv, **envp = NULL; + PyObject *func = Py_None, *user_data = NULL; + char *working_directory = NULL; + int flags = 0, _stdin = -1, _stdout = -1, _stderr = -1; + PyObject *pystdin = NULL, *pystdout = NULL, *pystderr = NULL; + gint *standard_input, *standard_output, *standard_error; + struct _PyGChildSetupData *callback_data = NULL; + GError *error = NULL; + GPid child_pid = -1; + Py_ssize_t len, i; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OsiOOOOO:glib.spawn_async", + kwlist, + &pyargv, &pyenvp, &working_directory, &flags, + &func, &user_data, + &pystdin, &pystdout, &pystderr)) + return NULL; + + if (pystdin && PyObject_IsTrue(pystdin)) + standard_input = &_stdin; + else + standard_input = NULL; + + if (pystdout && PyObject_IsTrue(pystdout)) + standard_output = &_stdout; + else + standard_output = NULL; + + if (pystderr && PyObject_IsTrue(pystderr)) + standard_error = &_stderr; + else + standard_error = NULL; + + /* parse argv */ + if (!PySequence_Check(pyargv)) { + PyErr_SetString(PyExc_TypeError, + "glib.spawn_async: " + "first argument must be a sequence of strings"); + return NULL; + } + len = PySequence_Length(pyargv); + argv = g_new0(char *, len + 1); + for (i = 0; i < len; ++i) { + PyObject *tmp = PySequence_ITEM(pyargv, i); + if (!PyString_Check(tmp)) { + PyErr_SetString(PyExc_TypeError, + "glib.spawn_async: " + "first argument must be a sequence of strings"); + g_free(argv); + Py_XDECREF(tmp); + return NULL; + } + argv[i] = PyString_AsString(tmp); + Py_DECREF(tmp); + } + + /* parse envp */ + if (pyenvp) { + if (!PySequence_Check(pyenvp)) { + PyErr_SetString(PyExc_TypeError, + "glib.spawn_async: " + "second argument must be a sequence of strings"); + g_free(argv); + return NULL; + } + len = PySequence_Length(pyenvp); + envp = g_new0(char *, len + 1); + for (i = 0; i < len; ++i) { + PyObject *tmp = PySequence_ITEM(pyenvp, i); + if (!PyString_Check(tmp)) { + PyErr_SetString(PyExc_TypeError, + "glib.spawn_async: " + "second argument must be a sequence of strings"); + g_free(envp); + Py_XDECREF(tmp); + g_free(argv); + return NULL; + } + envp[i] = PyString_AsString(tmp); + Py_DECREF(tmp); + } + } + + if (func != Py_None) { + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, "child_setup parameter must be callable or None"); + g_free(argv); + if (envp) + g_free(envp); + return NULL; + } + callback_data = g_new(struct _PyGChildSetupData, 1); + callback_data->func = func; + callback_data->data = user_data; + Py_INCREF(callback_data->func); + if (callback_data->data) + Py_INCREF(callback_data->data); + } + + if (!g_spawn_async_with_pipes(working_directory, argv, envp, flags, + (func != Py_None ? _pyg_spawn_async_callback : NULL), + callback_data, &child_pid, + standard_input, + standard_output, + standard_error, + &error)) + + + { + g_free(argv); + if (envp) g_free(envp); + if (callback_data) { + Py_DECREF(callback_data->func); + Py_XDECREF(callback_data->data); + g_free(callback_data); + } + pyglib_error_check(&error); + return NULL; + } + g_free(argv); + if (envp) g_free(envp); + + if (standard_input) + pystdin = PyInt_FromLong(*standard_input); + else { + Py_INCREF(Py_None); + pystdin = Py_None; + } + + if (standard_output) + pystdout = PyInt_FromLong(*standard_output); + else { + Py_INCREF(Py_None); + pystdout = Py_None; + } + + if (standard_error) + pystderr = PyInt_FromLong(*standard_error); + else { + Py_INCREF(Py_None); + pystderr = Py_None; + } + + return Py_BuildValue("NNNN", pyg_pid_new(child_pid), pystdin, pystdout, pystderr); +} + +void +pyg_spawn_register_types(PyObject *d) +{ + PyGPid_Type.tp_base = &PyInt_Type; + PYGLIB_REGISTER_TYPE(d, PyGPid_Type, "Pid"); +} |