1 // Copyright David Abrahams 2001.
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5
6 #include <boost/python/docstring_options.hpp>
7 #include <boost/python/object/function_object.hpp>
8 #include <boost/python/object/function_handle.hpp>
9 #include <boost/python/object/function_doc_signature.hpp>
10 #include <boost/python/errors.hpp>
11 #include <boost/python/str.hpp>
12 #include <boost/python/object_attributes.hpp>
13 #include <boost/python/args.hpp>
14 #include <boost/python/refcount.hpp>
15 #include <boost/python/extract.hpp>
16 #include <boost/python/tuple.hpp>
17 #include <boost/python/list.hpp>
18 #include <boost/python/ssize_t.hpp>
19
20 #include <boost/python/detail/signature.hpp>
21 #include <boost/python/detail/none.hpp>
22 #include <boost/mpl/vector/vector10.hpp>
23
24 #include <boost/bind.hpp>
25
26 #include <algorithm>
27 #include <cstring>
28
29 #if BOOST_PYTHON_DEBUG_ERROR_MESSAGES
30 # include <cstdio>
31 #endif
32
33 namespace boost { namespace python {
34 volatile bool docstring_options::show_user_defined_ = true;
35 volatile bool docstring_options::show_cpp_signatures_ = true;
36 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
37 volatile bool docstring_options::show_py_signatures_ = true;
38 #else
39 volatile bool docstring_options::show_py_signatures_ = false;
40 #endif
41 }}
42
43 namespace boost { namespace python { namespace objects {
44
~py_function_impl_base()45 py_function_impl_base::~py_function_impl_base()
46 {
47 }
48
max_arity() const49 unsigned py_function_impl_base::max_arity() const
50 {
51 return this->min_arity();
52 }
53
54 extern PyTypeObject function_type;
55
function(py_function const & implementation,python::detail::keyword const * names_and_defaults,unsigned num_keywords)56 function::function(
57 py_function const& implementation
58 #if BOOST_WORKAROUND(__EDG_VERSION__, == 245)
59 , python::detail::keyword const* names_and_defaults
60 #else
61 , python::detail::keyword const* const names_and_defaults
62 #endif
63 , unsigned num_keywords
64 )
65 : m_fn(implementation)
66 , m_nkeyword_values(0)
67 {
68 if (names_and_defaults != 0)
69 {
70 unsigned int max_arity = m_fn.max_arity();
71 unsigned int keyword_offset
72 = max_arity > num_keywords ? max_arity - num_keywords : 0;
73
74
75 ssize_t tuple_size = num_keywords ? max_arity : 0;
76 m_arg_names = object(handle<>(PyTuple_New(tuple_size)));
77
78 if (num_keywords != 0)
79 {
80 for (unsigned j = 0; j < keyword_offset; ++j)
81 PyTuple_SET_ITEM(m_arg_names.ptr(), j, incref(Py_None));
82 }
83
84 for (unsigned i = 0; i < num_keywords; ++i)
85 {
86 tuple kv;
87
88 python::detail::keyword const* const p = names_and_defaults + i;
89 if (p->default_value)
90 {
91 kv = make_tuple(p->name, p->default_value);
92 ++m_nkeyword_values;
93 }
94 else
95 {
96 kv = make_tuple(p->name);
97 }
98
99 PyTuple_SET_ITEM(
100 m_arg_names.ptr()
101 , i + keyword_offset
102 , incref(kv.ptr())
103 );
104 }
105 }
106
107 PyObject* p = this;
108 if (Py_TYPE(&function_type) == 0)
109 {
110 Py_TYPE(&function_type) = &PyType_Type;
111 ::PyType_Ready(&function_type);
112 }
113
114 (void)( // warning suppression for GCC
115 PyObject_INIT(p, &function_type)
116 );
117 }
118
~function()119 function::~function()
120 {
121 }
122
call(PyObject * args,PyObject * keywords) const123 PyObject* function::call(PyObject* args, PyObject* keywords) const
124 {
125 std::size_t n_unnamed_actual = PyTuple_GET_SIZE(args);
126 std::size_t n_keyword_actual = keywords ? PyDict_Size(keywords) : 0;
127 std::size_t n_actual = n_unnamed_actual + n_keyword_actual;
128
129 function const* f = this;
130
131 // Try overloads looking for a match
132 do
133 {
134 // Check for a plausible number of arguments
135 unsigned min_arity = f->m_fn.min_arity();
136 unsigned max_arity = f->m_fn.max_arity();
137
138 if (n_actual + f->m_nkeyword_values >= min_arity
139 && n_actual <= max_arity)
140 {
141 // This will be the args that actually get passed
142 handle<>inner_args(allow_null(borrowed(args)));
143
144 if (n_keyword_actual > 0 // Keyword arguments were supplied
145 || n_actual < min_arity) // or default keyword values are needed
146 {
147 if (f->m_arg_names.is_none())
148 {
149 // this overload doesn't accept keywords
150 inner_args = handle<>();
151 }
152 else
153 {
154 // "all keywords are none" is a special case
155 // indicating we will accept any number of keyword
156 // arguments
157 if (PyTuple_Size(f->m_arg_names.ptr()) == 0)
158 {
159 // no argument preprocessing
160 }
161 else if (n_actual > max_arity)
162 {
163 // too many arguments
164 inner_args = handle<>();
165 }
166 else
167 {
168 // build a new arg tuple, will adjust its size later
169 assert(max_arity <= static_cast<std::size_t>(ssize_t_max));
170 inner_args = handle<>(
171 PyTuple_New(static_cast<ssize_t>(max_arity)));
172
173 // Fill in the positional arguments
174 for (std::size_t i = 0; i < n_unnamed_actual; ++i)
175 PyTuple_SET_ITEM(inner_args.get(), i, incref(PyTuple_GET_ITEM(args, i)));
176
177 // Grab remaining arguments by name from the keyword dictionary
178 std::size_t n_actual_processed = n_unnamed_actual;
179
180 for (std::size_t arg_pos = n_unnamed_actual; arg_pos < max_arity ; ++arg_pos)
181 {
182 // Get the keyword[, value pair] corresponding
183 PyObject* kv = PyTuple_GET_ITEM(f->m_arg_names.ptr(), arg_pos);
184
185 // If there were any keyword arguments,
186 // look up the one we need for this
187 // argument position
188 PyObject* value = n_keyword_actual
189 ? PyDict_GetItem(keywords, PyTuple_GET_ITEM(kv, 0))
190 : 0;
191
192 if (!value)
193 {
194 // Not found; check if there's a default value
195 if (PyTuple_GET_SIZE(kv) > 1)
196 value = PyTuple_GET_ITEM(kv, 1);
197
198 if (!value)
199 {
200 // still not found; matching fails
201 PyErr_Clear();
202 inner_args = handle<>();
203 break;
204 }
205 }
206 else
207 {
208 ++n_actual_processed;
209 }
210
211 PyTuple_SET_ITEM(inner_args.get(), arg_pos, incref(value));
212 }
213
214 if (inner_args.get())
215 {
216 //check if we proccessed all the arguments
217 if(n_actual_processed < n_actual)
218 inner_args = handle<>();
219 }
220 }
221 }
222 }
223
224 // Call the function. Pass keywords in case it's a
225 // function accepting any number of keywords
226 PyObject* result = inner_args ? f->m_fn(inner_args.get(), keywords) : 0;
227
228 // If the result is NULL but no error was set, m_fn failed
229 // the argument-matching test.
230
231 // This assumes that all other error-reporters are
232 // well-behaved and never return NULL to python without
233 // setting an error.
234 if (result != 0 || PyErr_Occurred())
235 return result;
236 }
237 f = f->m_overloads.get();
238 }
239 while (f);
240 // None of the overloads matched; time to generate the error message
241 argument_error(args, keywords);
242 return 0;
243 }
244
signature(bool show_return_type) const245 object function::signature(bool show_return_type) const
246 {
247 py_function const& impl = m_fn;
248
249 python::detail::signature_element const* return_type = impl.signature();
250 python::detail::signature_element const* s = return_type + 1;
251
252 list formal_params;
253 if (impl.max_arity() == 0)
254 formal_params.append("void");
255
256 for (unsigned n = 0; n < impl.max_arity(); ++n)
257 {
258 if (s[n].basename == 0)
259 {
260 formal_params.append("...");
261 break;
262 }
263
264 str param(s[n].basename);
265 if (s[n].lvalue)
266 param += " {lvalue}";
267
268 if (m_arg_names) // None or empty tuple will test false
269 {
270 object kv(m_arg_names[n]);
271 if (kv)
272 {
273 char const* const fmt = len(kv) > 1 ? " %s=%r" : " %s";
274 param += fmt % kv;
275 }
276 }
277
278 formal_params.append(param);
279 }
280
281 if (show_return_type)
282 return "%s(%s) -> %s" % make_tuple(
283 m_name, str(", ").join(formal_params), return_type->basename);
284 return "%s(%s)" % make_tuple(
285 m_name, str(", ").join(formal_params));
286 }
287
signatures(bool show_return_type) const288 object function::signatures(bool show_return_type) const
289 {
290 list result;
291 for (function const* f = this; f; f = f->m_overloads.get()) {
292 result.append(f->signature(show_return_type));
293 }
294 return result;
295 }
296
argument_error(PyObject * args,PyObject *) const297 void function::argument_error(PyObject* args, PyObject* /*keywords*/) const
298 {
299 static handle<> exception(
300 PyErr_NewException(const_cast<char*>("Boost.Python.ArgumentError"), PyExc_TypeError, 0));
301
302 object message = "Python argument types in\n %s.%s("
303 % make_tuple(this->m_namespace, this->m_name);
304
305 list actual_args;
306 for (ssize_t i = 0; i < PyTuple_Size(args); ++i)
307 {
308 char const* name = PyTuple_GetItem(args, i)->ob_type->tp_name;
309 actual_args.append(str(name));
310 }
311 message += str(", ").join(actual_args);
312 message += ")\ndid not match C++ signature:\n ";
313 message += str("\n ").join(signatures());
314
315 #if BOOST_PYTHON_DEBUG_ERROR_MESSAGES
316 std::printf("\n--------\n%s\n--------\n", extract<const char*>(message)());
317 #endif
318 PyErr_SetObject(exception.get(), message.ptr());
319 throw_error_already_set();
320 }
321
add_overload(handle<function> const & overload_)322 void function::add_overload(handle<function> const& overload_)
323 {
324 function* parent = this;
325
326 while (parent->m_overloads)
327 parent = parent->m_overloads.get();
328
329 parent->m_overloads = overload_;
330
331 // If we have no documentation, get the docs from the overload
332 if (!m_doc)
333 m_doc = overload_->m_doc;
334 }
335
336 namespace
337 {
338 char const* const binary_operator_names[] =
339 {
340 "add__",
341 "and__",
342 "div__",
343 "divmod__",
344 "eq__",
345 "floordiv__",
346 "ge__",
347 "gt__",
348 "le__",
349 "lshift__",
350 "lt__",
351 "mod__",
352 "mul__",
353 "ne__",
354 "or__",
355 "pow__",
356 "radd__",
357 "rand__",
358 "rdiv__",
359 "rdivmod__",
360 "rfloordiv__",
361 "rlshift__",
362 "rmod__",
363 "rmul__",
364 "ror__",
365 "rpow__",
366 "rrshift__",
367 "rshift__",
368 "rsub__",
369 "rtruediv__",
370 "rxor__",
371 "sub__",
372 "truediv__",
373 "xor__"
374 };
375
376 struct less_cstring
377 {
operator ()boost::python::objects::__anon03f1c1270111::less_cstring378 bool operator()(char const* x, char const* y) const
379 {
380 return BOOST_CSTD_::strcmp(x,y) < 0;
381 }
382 };
383
is_binary_operator(char const * name)384 inline bool is_binary_operator(char const* name)
385 {
386 return name[0] == '_'
387 && name[1] == '_'
388 && std::binary_search(
389 &binary_operator_names[0]
390 , binary_operator_names + sizeof(binary_operator_names)/sizeof(*binary_operator_names)
391 , name + 2
392 , less_cstring()
393 );
394 }
395
396 // Something for the end of the chain of binary operators
not_implemented(PyObject *,PyObject *)397 PyObject* not_implemented(PyObject*, PyObject*)
398 {
399 Py_INCREF(Py_NotImplemented);
400 return Py_NotImplemented;
401 }
402
not_implemented_function()403 handle<function> not_implemented_function()
404 {
405
406 static object keeper(
407 function_object(
408 py_function(¬_implemented, mpl::vector1<void>(), 2)
409 , python::detail::keyword_range())
410 );
411 return handle<function>(borrowed(downcast<function>(keeper.ptr())));
412 }
413 }
414
add_to_namespace(object const & name_space,char const * name_,object const & attribute)415 void function::add_to_namespace(
416 object const& name_space, char const* name_, object const& attribute)
417 {
418 add_to_namespace(name_space, name_, attribute, 0);
419 }
420
421 namespace detail
422 {
423 extern char py_signature_tag[];
424 extern char cpp_signature_tag[];
425 }
426
add_to_namespace(object const & name_space,char const * name_,object const & attribute,char const * doc)427 void function::add_to_namespace(
428 object const& name_space, char const* name_, object const& attribute, char const* doc)
429 {
430 str const name(name_);
431 PyObject* const ns = name_space.ptr();
432
433 if (attribute.ptr()->ob_type == &function_type)
434 {
435 function* new_func = downcast<function>(attribute.ptr());
436 handle<> dict;
437
438 #if PY_VERSION_HEX < 0x03000000
439 // Old-style class gone in Python 3
440 if (PyClass_Check(ns))
441 dict = handle<>(borrowed(((PyClassObject*)ns)->cl_dict));
442 else
443 #endif
444 if (PyType_Check(ns))
445 dict = handle<>(borrowed(((PyTypeObject*)ns)->tp_dict));
446 else
447 dict = handle<>(PyObject_GetAttrString(ns, const_cast<char*>("__dict__")));
448
449 if (dict == 0)
450 throw_error_already_set();
451
452 handle<> existing(allow_null(::PyObject_GetItem(dict.get(), name.ptr())));
453
454 if (existing)
455 {
456 if (existing->ob_type == &function_type)
457 {
458 new_func->add_overload(
459 handle<function>(
460 borrowed(
461 downcast<function>(existing.get())
462 )
463 )
464 );
465 }
466 else if (existing->ob_type == &PyStaticMethod_Type)
467 {
468 char const* name_space_name = extract<char const*>(name_space.attr("__name__"));
469
470 ::PyErr_Format(
471 PyExc_RuntimeError
472 , "Boost.Python - All overloads must be exported "
473 "before calling \'class_<...>(\"%s\").staticmethod(\"%s\")\'"
474 , name_space_name
475 , name_
476 );
477 throw_error_already_set();
478 }
479 }
480 else if (is_binary_operator(name_))
481 {
482 // Binary operators need an additional overload which
483 // returns NotImplemented, so that Python will try the
484 // __rxxx__ functions on the other operand. We add this
485 // when no overloads for the operator already exist.
486 new_func->add_overload(not_implemented_function());
487 }
488
489 // A function is named the first time it is added to a namespace.
490 if (new_func->name().is_none())
491 new_func->m_name = name;
492
493 handle<> name_space_name(
494 allow_null(::PyObject_GetAttrString(name_space.ptr(), const_cast<char*>("__name__"))));
495
496 if (name_space_name)
497 new_func->m_namespace = object(name_space_name);
498 }
499
500 // The PyObject_GetAttrString() or PyObject_GetItem calls above may
501 // have left an active error
502 PyErr_Clear();
503 if (PyObject_SetAttr(ns, name.ptr(), attribute.ptr()) < 0)
504 throw_error_already_set();
505
506 object mutable_attribute(attribute);
507 /*
508 if (doc != 0 && docstring_options::show_user_defined_)
509 {
510 // Accumulate documentation
511
512 if (
513 PyObject_HasAttrString(mutable_attribute.ptr(), "__doc__")
514 && mutable_attribute.attr("__doc__"))
515 {
516 mutable_attribute.attr("__doc__") += "\n\n";
517 mutable_attribute.attr("__doc__") += doc;
518 }
519 else {
520 mutable_attribute.attr("__doc__") = doc;
521 }
522 }
523
524 if (docstring_options::show_signatures_)
525 {
526 if ( PyObject_HasAttrString(mutable_attribute.ptr(), "__doc__")
527 && mutable_attribute.attr("__doc__")) {
528 mutable_attribute.attr("__doc__") += (
529 mutable_attribute.attr("__doc__")[-1] != "\n" ? "\n\n" : "\n");
530 }
531 else {
532 mutable_attribute.attr("__doc__") = "";
533 }
534 function* f = downcast<function>(attribute.ptr());
535 mutable_attribute.attr("__doc__") += str("\n ").join(make_tuple(
536 "C++ signature:", f->signature(true)));
537 }
538 */
539 str _doc;
540
541 if (docstring_options::show_py_signatures_)
542 {
543 _doc += str(const_cast<const char*>(detail::py_signature_tag));
544 }
545 if (doc != 0 && docstring_options::show_user_defined_)
546 _doc += doc;
547
548 if (docstring_options::show_cpp_signatures_)
549 {
550 _doc += str(const_cast<const char*>(detail::cpp_signature_tag));
551 }
552 if(_doc)
553 {
554 object mutable_attribute(attribute);
555 mutable_attribute.attr("__doc__")= _doc;
556 }
557 }
558
add_to_namespace(object const & name_space,char const * name,object const & attribute)559 BOOST_PYTHON_DECL void add_to_namespace(
560 object const& name_space, char const* name, object const& attribute)
561 {
562 function::add_to_namespace(name_space, name, attribute, 0);
563 }
564
add_to_namespace(object const & name_space,char const * name,object const & attribute,char const * doc)565 BOOST_PYTHON_DECL void add_to_namespace(
566 object const& name_space, char const* name, object const& attribute, char const* doc)
567 {
568 function::add_to_namespace(name_space, name, attribute, doc);
569 }
570
571
572 namespace
573 {
574 struct bind_return
575 {
bind_returnboost::python::objects::__anon03f1c1270211::bind_return576 bind_return(PyObject*& result, function const* f, PyObject* args, PyObject* keywords)
577 : m_result(result)
578 , m_f(f)
579 , m_args(args)
580 , m_keywords(keywords)
581 {}
582
operator ()boost::python::objects::__anon03f1c1270211::bind_return583 void operator()() const
584 {
585 m_result = m_f->call(m_args, m_keywords);
586 }
587
588 private:
589 PyObject*& m_result;
590 function const* m_f;
591 PyObject* m_args;
592 PyObject* m_keywords;
593 };
594 }
595
596 extern "C"
597 {
598 // Stolen from Python's funcobject.c
599 static PyObject *
function_descr_get(PyObject * func,PyObject * obj,PyObject * type_)600 function_descr_get(PyObject *func, PyObject *obj, PyObject *type_)
601 {
602 #if PY_VERSION_HEX >= 0x03000000
603 // The implement is different in Python 3 because of the removal of unbound method
604 if (obj == Py_None || obj == NULL) {
605 Py_INCREF(func);
606 return func;
607 }
608 return PyMethod_New(func, obj);
609 #else
610 if (obj == Py_None)
611 obj = NULL;
612 return PyMethod_New(func, obj, type_);
613 #endif
614 }
615
616 static void
function_dealloc(PyObject * p)617 function_dealloc(PyObject* p)
618 {
619 delete static_cast<function*>(p);
620 }
621
622 static PyObject *
function_call(PyObject * func,PyObject * args,PyObject * kw)623 function_call(PyObject *func, PyObject *args, PyObject *kw)
624 {
625 PyObject* result = 0;
626 handle_exception(bind_return(result, static_cast<function*>(func), args, kw));
627 return result;
628 }
629
630 //
631 // Here we're using the function's tp_getset rather than its
632 // tp_members to set up __doc__ and __name__, because tp_members
633 // really depends on having a POD object type (it relies on
634 // offsets). It might make sense to reformulate function as a POD
635 // at some point, but this is much more expedient.
636 //
function_get_doc(PyObject * op,void *)637 static PyObject* function_get_doc(PyObject* op, void*)
638 {
639 function* f = downcast<function>(op);
640 list signatures = function_doc_signature_generator::function_doc_signatures(f);
641 if(!signatures) return python::detail::none();
642 signatures.reverse();
643 return python::incref( str("\n").join(signatures).ptr());
644 }
645
function_set_doc(PyObject * op,PyObject * doc,void *)646 static int function_set_doc(PyObject* op, PyObject* doc, void*)
647 {
648 function* f = downcast<function>(op);
649 f->doc(doc ? object(python::detail::borrowed_reference(doc)) : object());
650 return 0;
651 }
652
function_get_name(PyObject * op,void *)653 static PyObject* function_get_name(PyObject* op, void*)
654 {
655 function* f = downcast<function>(op);
656 if (f->name().is_none())
657 #if PY_VERSION_HEX >= 0x03000000
658 return PyUnicode_InternFromString("<unnamed Boost.Python function>");
659 #else
660 return PyString_InternFromString("<unnamed Boost.Python function>");
661 #endif
662 else
663 return python::incref(f->name().ptr());
664 }
665
666 // We add a dummy __class__ attribute in order to fool PyDoc into
667 // treating these as built-in functions and scanning their
668 // documentation
function_get_class(PyObject *,void *)669 static PyObject* function_get_class(PyObject* /*op*/, void*)
670 {
671 return python::incref(upcast<PyObject>(&PyCFunction_Type));
672 }
673
function_get_module(PyObject * op,void *)674 static PyObject* function_get_module(PyObject* op, void*)
675 {
676 function* f = downcast<function>(op);
677 object const& ns = f->get_namespace();
678 if (!ns.is_none()) {
679 return python::incref(ns.ptr());
680 }
681 PyErr_SetString(
682 PyExc_AttributeError, const_cast<char*>(
683 "Boost.Python function __module__ unknown."));
684 return 0;
685 }
686 }
687
688 static PyGetSetDef function_getsetlist[] = {
689 {const_cast<char*>("__name__"), (getter)function_get_name, 0, 0, 0 },
690 {const_cast<char*>("func_name"), (getter)function_get_name, 0, 0, 0 },
691 {const_cast<char*>("__module__"), (getter)function_get_module, 0, 0, 0 },
692 {const_cast<char*>("func_module"), (getter)function_get_module, 0, 0, 0 },
693 {const_cast<char*>("__class__"), (getter)function_get_class, 0, 0, 0 }, // see note above
694 {const_cast<char*>("__doc__"), (getter)function_get_doc, (setter)function_set_doc, 0, 0},
695 {const_cast<char*>("func_doc"), (getter)function_get_doc, (setter)function_set_doc, 0, 0},
696 {NULL, 0, 0, 0, 0} /* Sentinel */
697 };
698
699 PyTypeObject function_type = {
700 PyVarObject_HEAD_INIT(NULL, 0)
701 const_cast<char*>("Boost.Python.function"),
702 sizeof(function),
703 0,
704 (destructor)function_dealloc, /* tp_dealloc */
705 0, /* tp_print */
706 0, /* tp_getattr */
707 0, /* tp_setattr */
708 0, /* tp_compare */
709 0, //(reprfunc)func_repr, /* tp_repr */
710 0, /* tp_as_number */
711 0, /* tp_as_sequence */
712 0, /* tp_as_mapping */
713 0, /* tp_hash */
714 function_call, /* tp_call */
715 0, /* tp_str */
716 0, // PyObject_GenericGetAttr, /* tp_getattro */
717 0, // PyObject_GenericSetAttr, /* tp_setattro */
718 0, /* tp_as_buffer */
719 Py_TPFLAGS_DEFAULT /* | Py_TPFLAGS_HAVE_GC */,/* tp_flags */
720 0, /* tp_doc */
721 0, // (traverseproc)func_traverse, /* tp_traverse */
722 0, /* tp_clear */
723 0, /* tp_richcompare */
724 0, //offsetof(PyFunctionObject, func_weakreflist), /* tp_weaklistoffset */
725 0, /* tp_iter */
726 0, /* tp_iternext */
727 0, /* tp_methods */
728 0, // func_memberlist, /* tp_members */
729 function_getsetlist, /* tp_getset */
730 0, /* tp_base */
731 0, /* tp_dict */
732 function_descr_get, /* tp_descr_get */
733 0, /* tp_descr_set */
734 0, //offsetof(PyFunctionObject, func_dict), /* tp_dictoffset */
735 0, /* tp_init */
736 0, /* tp_alloc */
737 0, /* tp_new */
738 0, /* tp_free */
739 0, /* tp_is_gc */
740 0, /* tp_bases */
741 0, /* tp_mro */
742 0, /* tp_cache */
743 0, /* tp_subclasses */
744 0, /* tp_weaklist */
745 #if PYTHON_API_VERSION >= 1012
746 0 /* tp_del */
747 #endif
748 };
749
function_object(py_function const & f,python::detail::keyword_range const & keywords)750 object function_object(
751 py_function const& f
752 , python::detail::keyword_range const& keywords)
753 {
754 return python::object(
755 python::detail::new_non_null_reference(
756 new function(
757 f, keywords.first, keywords.second - keywords.first)));
758 }
759
function_object(py_function const & f)760 object function_object(py_function const& f)
761 {
762 return function_object(f, python::detail::keyword_range());
763 }
764
765
function_handle_impl(py_function const & f)766 handle<> function_handle_impl(py_function const& f)
767 {
768 return python::handle<>(
769 allow_null(
770 new function(f, 0, 0)));
771 }
772
773 } // namespace objects
774
775 namespace detail
776 {
make_raw_function(objects::py_function f)777 object BOOST_PYTHON_DECL make_raw_function(objects::py_function f)
778 {
779 static keyword k;
780
781 return objects::function_object(
782 f
783 , keyword_range(&k,&k));
784 }
pure_virtual_called()785 void BOOST_PYTHON_DECL pure_virtual_called()
786 {
787 PyErr_SetString(
788 PyExc_RuntimeError, const_cast<char*>("Pure virtual function called"));
789 throw_error_already_set();
790 }
791 }
792
793 }} // namespace boost::python
794