attr.h revision 11986:c12e4625ab56
1/* 2 pybind11/pybind11.h: Infrastructure for processing custom 3 type and function attributes 4 5 Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> 6 7 All rights reserved. Use of this source code is governed by a 8 BSD-style license that can be found in the LICENSE file. 9*/ 10 11#pragma once 12 13#include "cast.h" 14 15NAMESPACE_BEGIN(pybind11) 16 17/// Annotation for methods 18struct is_method { handle class_; is_method(const handle &c) : class_(c) { } }; 19 20/// Annotation for operators 21struct is_operator { }; 22 23/// Annotation for parent scope 24struct scope { handle value; scope(const handle &s) : value(s) { } }; 25 26/// Annotation for documentation 27struct doc { const char *value; doc(const char *value) : value(value) { } }; 28 29/// Annotation for function names 30struct name { const char *value; name(const char *value) : value(value) { } }; 31 32/// Annotation indicating that a function is an overload associated with a given "sibling" 33struct sibling { handle value; sibling(const handle &value) : value(value.ptr()) { } }; 34 35/// Annotation indicating that a class derives from another given type 36template <typename T> struct base { 37 PYBIND11_DEPRECATED("base<T>() was deprecated in favor of specifying 'T' as a template argument to class_") 38 base() { } 39}; 40 41/// Keep patient alive while nurse lives 42template <int Nurse, int Patient> struct keep_alive { }; 43 44/// Annotation indicating that a class is involved in a multiple inheritance relationship 45struct multiple_inheritance { }; 46 47/// Annotation which enables dynamic attributes, i.e. adds `__dict__` to a class 48struct dynamic_attr { }; 49 50/// Annotation to mark enums as an arithmetic type 51struct arithmetic { }; 52 53NAMESPACE_BEGIN(detail) 54/* Forward declarations */ 55enum op_id : int; 56enum op_type : int; 57struct undefined_t; 58template <op_id id, op_type ot, typename L = undefined_t, typename R = undefined_t> struct op_; 59template <typename... Args> struct init; 60template <typename... Args> struct init_alias; 61inline void keep_alive_impl(int Nurse, int Patient, handle args, handle ret); 62 63/// Internal data structure which holds metadata about a keyword argument 64struct argument_record { 65 const char *name; ///< Argument name 66 const char *descr; ///< Human-readable version of the argument value 67 handle value; ///< Associated Python object 68 69 argument_record(const char *name, const char *descr, handle value) 70 : name(name), descr(descr), value(value) { } 71}; 72 73/// Internal data structure which holds metadata about a bound function (signature, overloads, etc.) 74struct function_record { 75 function_record() 76 : is_constructor(false), is_stateless(false), is_operator(false), 77 has_args(false), has_kwargs(false), is_method(false) { } 78 79 /// Function name 80 char *name = nullptr; /* why no C++ strings? They generate heavier code.. */ 81 82 // User-specified documentation string 83 char *doc = nullptr; 84 85 /// Human-readable version of the function signature 86 char *signature = nullptr; 87 88 /// List of registered keyword arguments 89 std::vector<argument_record> args; 90 91 /// Pointer to lambda function which converts arguments and performs the actual call 92 handle (*impl) (function_record *, handle, handle, handle) = nullptr; 93 94 /// Storage for the wrapped function pointer and captured data, if any 95 void *data[3] = { }; 96 97 /// Pointer to custom destructor for 'data' (if needed) 98 void (*free_data) (function_record *ptr) = nullptr; 99 100 /// Return value policy associated with this function 101 return_value_policy policy = return_value_policy::automatic; 102 103 /// True if name == '__init__' 104 bool is_constructor : 1; 105 106 /// True if this is a stateless function pointer 107 bool is_stateless : 1; 108 109 /// True if this is an operator (__add__), etc. 110 bool is_operator : 1; 111 112 /// True if the function has a '*args' argument 113 bool has_args : 1; 114 115 /// True if the function has a '**kwargs' argument 116 bool has_kwargs : 1; 117 118 /// True if this is a method 119 bool is_method : 1; 120 121 /// Number of arguments 122 uint16_t nargs; 123 124 /// Python method object 125 PyMethodDef *def = nullptr; 126 127 /// Python handle to the parent scope (a class or a module) 128 handle scope; 129 130 /// Python handle to the sibling function representing an overload chain 131 handle sibling; 132 133 /// Pointer to next overload 134 function_record *next = nullptr; 135}; 136 137/// Special data structure which (temporarily) holds metadata about a bound class 138struct type_record { 139 PYBIND11_NOINLINE type_record() { } 140 141 /// Handle to the parent scope 142 handle scope; 143 144 /// Name of the class 145 const char *name = nullptr; 146 147 // Pointer to RTTI type_info data structure 148 const std::type_info *type = nullptr; 149 150 /// How large is the underlying C++ type? 151 size_t type_size = 0; 152 153 /// How large is pybind11::instance<type>? 154 size_t instance_size = 0; 155 156 /// Function pointer to class_<..>::init_holder 157 void (*init_holder)(PyObject *, const void *) = nullptr; 158 159 /// Function pointer to class_<..>::dealloc 160 void (*dealloc)(PyObject *) = nullptr; 161 162 /// List of base classes of the newly created type 163 list bases; 164 165 /// Optional docstring 166 const char *doc = nullptr; 167 168 /// Multiple inheritance marker 169 bool multiple_inheritance = false; 170 171 /// Does the class manage a __dict__? 172 bool dynamic_attr = false; 173 174 PYBIND11_NOINLINE void add_base(const std::type_info *base, void *(*caster)(void *)) { 175 auto base_info = detail::get_type_info(*base, false); 176 if (!base_info) { 177 std::string tname(base->name()); 178 detail::clean_type_id(tname); 179 pybind11_fail("generic_type: type \"" + std::string(name) + 180 "\" referenced unknown base type \"" + tname + "\""); 181 } 182 183 bases.append((PyObject *) base_info->type); 184 185 if (base_info->type->tp_dictoffset != 0) 186 dynamic_attr = true; 187 188 if (caster) 189 base_info->implicit_casts.push_back(std::make_pair(type, caster)); 190 } 191}; 192 193/** 194 * Partial template specializations to process custom attributes provided to 195 * cpp_function_ and class_. These are either used to initialize the respective 196 * fields in the type_record and function_record data structures or executed at 197 * runtime to deal with custom call policies (e.g. keep_alive). 198 */ 199template <typename T, typename SFINAE = void> struct process_attribute; 200 201template <typename T> struct process_attribute_default { 202 /// Default implementation: do nothing 203 static void init(const T &, function_record *) { } 204 static void init(const T &, type_record *) { } 205 static void precall(handle) { } 206 static void postcall(handle, handle) { } 207}; 208 209/// Process an attribute specifying the function's name 210template <> struct process_attribute<name> : process_attribute_default<name> { 211 static void init(const name &n, function_record *r) { r->name = const_cast<char *>(n.value); } 212}; 213 214/// Process an attribute specifying the function's docstring 215template <> struct process_attribute<doc> : process_attribute_default<doc> { 216 static void init(const doc &n, function_record *r) { r->doc = const_cast<char *>(n.value); } 217}; 218 219/// Process an attribute specifying the function's docstring (provided as a C-style string) 220template <> struct process_attribute<const char *> : process_attribute_default<const char *> { 221 static void init(const char *d, function_record *r) { r->doc = const_cast<char *>(d); } 222 static void init(const char *d, type_record *r) { r->doc = const_cast<char *>(d); } 223}; 224template <> struct process_attribute<char *> : process_attribute<const char *> { }; 225 226/// Process an attribute indicating the function's return value policy 227template <> struct process_attribute<return_value_policy> : process_attribute_default<return_value_policy> { 228 static void init(const return_value_policy &p, function_record *r) { r->policy = p; } 229}; 230 231/// Process an attribute which indicates that this is an overloaded function associated with a given sibling 232template <> struct process_attribute<sibling> : process_attribute_default<sibling> { 233 static void init(const sibling &s, function_record *r) { r->sibling = s.value; } 234}; 235 236/// Process an attribute which indicates that this function is a method 237template <> struct process_attribute<is_method> : process_attribute_default<is_method> { 238 static void init(const is_method &s, function_record *r) { r->is_method = true; r->scope = s.class_; } 239}; 240 241/// Process an attribute which indicates the parent scope of a method 242template <> struct process_attribute<scope> : process_attribute_default<scope> { 243 static void init(const scope &s, function_record *r) { r->scope = s.value; } 244}; 245 246/// Process an attribute which indicates that this function is an operator 247template <> struct process_attribute<is_operator> : process_attribute_default<is_operator> { 248 static void init(const is_operator &, function_record *r) { r->is_operator = true; } 249}; 250 251/// Process a keyword argument attribute (*without* a default value) 252template <> struct process_attribute<arg> : process_attribute_default<arg> { 253 static void init(const arg &a, function_record *r) { 254 if (r->is_method && r->args.empty()) 255 r->args.emplace_back("self", nullptr, handle()); 256 r->args.emplace_back(a.name, nullptr, handle()); 257 } 258}; 259 260/// Process a keyword argument attribute (*with* a default value) 261template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> { 262 static void init(const arg_v &a, function_record *r) { 263 if (r->is_method && r->args.empty()) 264 r->args.emplace_back("self", nullptr, handle()); 265 266 if (!a.value) { 267#if !defined(NDEBUG) 268 auto descr = "'" + std::string(a.name) + ": " + a.type + "'"; 269 if (r->is_method) { 270 if (r->name) 271 descr += " in method '" + (std::string) str(r->scope) + "." + (std::string) r->name + "'"; 272 else 273 descr += " in method of '" + (std::string) str(r->scope) + "'"; 274 } else if (r->name) { 275 descr += " in function named '" + (std::string) r->name + "'"; 276 } 277 pybind11_fail("arg(): could not convert default keyword argument " 278 + descr + " into a Python object (type not registered yet?)"); 279#else 280 pybind11_fail("arg(): could not convert default keyword argument " 281 "into a Python object (type not registered yet?). " 282 "Compile in debug mode for more information."); 283#endif 284 } 285 r->args.emplace_back(a.name, a.descr, a.value.inc_ref()); 286 } 287}; 288 289/// Process a parent class attribute 290template <typename T> 291struct process_attribute<T, enable_if_t<is_pyobject<T>::value>> : process_attribute_default<handle> { 292 static void init(const handle &h, type_record *r) { r->bases.append(h); } 293}; 294 295/// Process a parent class attribute (deprecated, does not support multiple inheritance) 296template <typename T> 297struct process_attribute<base<T>> : process_attribute_default<base<T>> { 298 static void init(const base<T> &, type_record *r) { r->add_base(&typeid(T), nullptr); } 299}; 300 301/// Process a multiple inheritance attribute 302template <> 303struct process_attribute<multiple_inheritance> : process_attribute_default<multiple_inheritance> { 304 static void init(const multiple_inheritance &, type_record *r) { r->multiple_inheritance = true; } 305}; 306 307template <> 308struct process_attribute<dynamic_attr> : process_attribute_default<dynamic_attr> { 309 static void init(const dynamic_attr &, type_record *r) { r->dynamic_attr = true; } 310}; 311 312 313/// Process an 'arithmetic' attribute for enums (does nothing here) 314template <> 315struct process_attribute<arithmetic> : process_attribute_default<arithmetic> {}; 316 317/*** 318 * Process a keep_alive call policy -- invokes keep_alive_impl during the 319 * pre-call handler if both Nurse, Patient != 0 and use the post-call handler 320 * otherwise 321 */ 322template <int Nurse, int Patient> struct process_attribute<keep_alive<Nurse, Patient>> : public process_attribute_default<keep_alive<Nurse, Patient>> { 323 template <int N = Nurse, int P = Patient, enable_if_t<N != 0 && P != 0, int> = 0> 324 static void precall(handle args) { keep_alive_impl(Nurse, Patient, args, handle()); } 325 template <int N = Nurse, int P = Patient, enable_if_t<N != 0 && P != 0, int> = 0> 326 static void postcall(handle, handle) { } 327 template <int N = Nurse, int P = Patient, enable_if_t<N == 0 || P == 0, int> = 0> 328 static void precall(handle) { } 329 template <int N = Nurse, int P = Patient, enable_if_t<N == 0 || P == 0, int> = 0> 330 static void postcall(handle args, handle ret) { keep_alive_impl(Nurse, Patient, args, ret); } 331}; 332 333/// Recursively iterate over variadic template arguments 334template <typename... Args> struct process_attributes { 335 static void init(const Args&... args, function_record *r) { 336 int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::init(args, r), 0) ... }; 337 ignore_unused(unused); 338 } 339 static void init(const Args&... args, type_record *r) { 340 int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::init(args, r), 0) ... }; 341 ignore_unused(unused); 342 } 343 static void precall(handle fn_args) { 344 int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::precall(fn_args), 0) ... }; 345 ignore_unused(unused); 346 } 347 static void postcall(handle fn_args, handle fn_ret) { 348 int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::postcall(fn_args, fn_ret), 0) ... }; 349 ignore_unused(unused); 350 } 351}; 352 353/// Check the number of named arguments at compile time 354template <typename... Extra, 355 size_t named = constexpr_sum(std::is_base_of<arg, Extra>::value...), 356 size_t self = constexpr_sum(std::is_same<is_method, Extra>::value...)> 357constexpr bool expected_num_args(size_t nargs) { 358 return named == 0 || (self + named) == nargs; 359} 360 361NAMESPACE_END(detail) 362NAMESPACE_END(pybind11) 363