|
6 | 6 |
|
7 | 7 | #include <boost/python/object/function.hpp> |
8 | 8 | #include <numeric> |
| 9 | +#include <boost/python/errors.hpp> |
| 10 | +#include <boost/python/objects.hpp> |
9 | 11 |
|
10 | 12 | namespace boost { namespace python { namespace objects { |
11 | 13 |
|
@@ -28,7 +30,7 @@ function::~function() |
28 | 30 |
|
29 | 31 | PyObject* function::call(PyObject* args, PyObject* keywords) const |
30 | 32 | { |
31 | | - int nargs = PyTuple_GET_SIZE(args); |
| 33 | + std::size_t nargs = PyTuple_GET_SIZE(args); |
32 | 34 | function const* f = this; |
33 | 35 | do |
34 | 36 | { |
@@ -63,6 +65,8 @@ void function::argument_error(PyObject* args, PyObject* keywords) const |
63 | 65 |
|
64 | 66 | void function::add_overload(function* overload) |
65 | 67 | { |
| 68 | + Py_XINCREF(overload); |
| 69 | + |
66 | 70 | function* parent = this; |
67 | 71 |
|
68 | 72 | while (parent->m_overloads != 0) |
@@ -72,6 +76,42 @@ void function::add_overload(function* overload) |
72 | 76 | parent->m_overloads = overload; |
73 | 77 | } |
74 | 78 |
|
| 79 | +void function::add_to_namespace( |
| 80 | + PyObject* name_space, char const* name_, PyObject* attribute_) |
| 81 | +{ |
| 82 | + ref attribute(attribute_, ref::increment_count); |
| 83 | + string name(name_); |
| 84 | + |
| 85 | + if (attribute_->ob_type == &function_type) |
| 86 | + { |
| 87 | + PyObject* dict = 0; |
| 88 | + |
| 89 | + if (PyClass_Check(name_space)) |
| 90 | + dict = ((PyClassObject*)name_space)->cl_dict; |
| 91 | + else if (PyType_Check(name_space)) |
| 92 | + dict = ((PyTypeObject*)name_space)->tp_dict; |
| 93 | + else |
| 94 | + dict = PyObject_GetAttrString(name_space, "__dict__"); |
| 95 | + |
| 96 | + if (dict == 0) |
| 97 | + throw error_already_set(); |
| 98 | + |
| 99 | + ref existing(PyObject_GetItem(dict, name.get()), ref::null_ok); |
| 100 | + |
| 101 | + if (existing.get() && existing->ob_type == &function_type) |
| 102 | + { |
| 103 | + static_cast<function*>(existing.get())->add_overload( |
| 104 | + static_cast<function*>(attribute_)); |
| 105 | + return; |
| 106 | + } |
| 107 | + } |
| 108 | + |
| 109 | + // The PyObject_GetAttrString() call above left an active error |
| 110 | + PyErr_Clear(); |
| 111 | + if (PyObject_SetAttr(name_space, name.get(), attribute_) < 0) |
| 112 | + throw error_already_set(); |
| 113 | +} |
| 114 | + |
75 | 115 | extern "C" |
76 | 116 | { |
77 | 117 | // Stolen from Python's funcobject.c |
|