Adonthell  0.4
py_callback.cc
Go to the documentation of this file.
1 /*
2  $Id: py_callback.cc,v 1.11 2004/02/02 06:38:01 ksterker Exp $
3 
4  Copyright (C) 2001/2002 Kai Sterker <kaisterker@linuxgames.com>
5  Part of the Adonthell Project http://adonthell.linuxgames.com
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 
16 /**
17  * @file py_callback.cc
18  * @author Kai Sterker <kaisterker@linuxgames.com>
19  *
20  * @brief Defines the py_callback class.
21  *
22  *
23  */
24 
25 
26 #include "py_callback.h"
27 #include "python_class.h"
28 
29 // 'hack' to aid restoring of callbacks from file
30 PyObject *py_callback::instance = NULL;
31 
32 // default constructor
34 {
35  function = NULL;
36  arguments = NULL;
37 }
38 
39 // preferred constructor
40 py_callback::py_callback (PyObject *func, PyObject *args)
41 {
42  function = func;
43  arguments = args;
44  Py_XINCREF (function);
45  Py_XINCREF (arguments);
46 }
47 
48 // dtor
50 {
51  Py_XDECREF (function);
52  Py_XDECREF (arguments);
53 }
54 
55 // calls the python function without argument
57 {
58  PyObject *py_arg = arguments ? Py_BuildValue ("(O)",arguments) : NULL;
59  PyObject* val = make_call (py_arg);
60  Py_XDECREF (val);
61 }
62 
63 // calls the python function returning a boolean
65 {
66  int retval = 1;
67 
68  PyObject *py_arg = arguments ? Py_BuildValue ("(O)",arguments) : NULL;
69  PyObject* val = make_call (py_arg);
70 
71  if (val) retval = PyInt_AsLong (val);
72  Py_XDECREF (val);
73 
74  return retval != 0;
75 }
76 
77 // calls the python function with an integer as argument
79 {
80  PyObject *py_arg;
81 
82  if (arguments) py_arg = Py_BuildValue ("(i,O)", arg, arguments);
83  else py_arg = Py_BuildValue ("(i)", arg);
84 
85  PyObject * val = make_call (py_arg);
86  Py_XDECREF (val);
87 }
88 
89 // save callback to a file
90 void py_callback::put_state (ogzstream & file) const
91 {
92  std::string name = "";
93 
94  // get name of callback function
95  if (function) {
96  PyObject *p_name = PyObject_GetAttrString (function, "__name__");
97  if (PyString_Check (p_name)) name = PyString_AsString (p_name);
98  else fprintf (stderr, "*** error: py_callback::put_state: Failed to retrieve callback name!");
99 
100  // cleanup
101  Py_XDECREF (p_name);
102  }
103 
104  name >> file;
105 
106  // NOTE: extra arguments need to be a tuple containing only ints or strings.
107  if (arguments != NULL)
108  {
109  true >> file;
110  python::put_tuple (arguments, file);
111  }
112  else false >> file;
113 }
114 
115 // restore callback from a file
117 {
118  std::string name;
119  bool has_args;
120 
121  name << file;
122  has_args << file;
123 
124  // load arguments. No need to INCREF as get_tuple returns new instance.
125  if (has_args) arguments = python::get_tuple (file);
126 
127  // check that we have a valid instance that contains our callback
128  if (instance == NULL)
129  {
130  fprintf (stderr, "*** error: py_callback::get_state: Invalid instance!\n");
131  return false;
132  }
133 
134  // get our callback from the class or module. No need to INCREF
135  // as GetAttrString returns a new instance.
136  function = PyObject_GetAttrString (instance, (char *) name.c_str ());
137 
138  // sanity check
139  if (!PyCallable_Check (function))
140  {
141  fprintf (stderr, "*** error: py_callback::get_state: Setting callback '%s' failed!\n", name.c_str ());
142  return false;
143  }
144 
145  return true;
146 }
147 
148 // the actual python callback call
149 PyObject *py_callback::make_call (PyObject *args)
150 {
151  if (function == NULL) return NULL;
152 
153  PyObject * val = PyObject_CallObject (function, args);
154  Py_XDECREF (args);
155 
156 #ifdef PY_DEBUG
158 #endif
159 
160  return val;
161 }