attr.h revision 11986:c12e4625ab56
1955SN/A/* 2955SN/A pybind11/pybind11.h: Infrastructure for processing custom 31762SN/A type and function attributes 4955SN/A 5955SN/A Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> 6955SN/A 7955SN/A All rights reserved. Use of this source code is governed by a 8955SN/A BSD-style license that can be found in the LICENSE file. 9955SN/A*/ 10955SN/A 11955SN/A#pragma once 12955SN/A 13955SN/A#include "cast.h" 14955SN/A 15955SN/ANAMESPACE_BEGIN(pybind11) 16955SN/A 17955SN/A/// Annotation for methods 18955SN/Astruct is_method { handle class_; is_method(const handle &c) : class_(c) { } }; 19955SN/A 20955SN/A/// Annotation for operators 21955SN/Astruct is_operator { }; 22955SN/A 23955SN/A/// Annotation for parent scope 24955SN/Astruct scope { handle value; scope(const handle &s) : value(s) { } }; 25955SN/A 26955SN/A/// Annotation for documentation 27955SN/Astruct doc { const char *value; doc(const char *value) : value(value) { } }; 282665Ssaidi@eecs.umich.edu 294762Snate@binkert.org/// Annotation for function names 30955SN/Astruct name { const char *value; name(const char *value) : value(value) { } }; 315522Snate@binkert.org 326143Snate@binkert.org/// Annotation indicating that a function is an overload associated with a given "sibling" 334762Snate@binkert.orgstruct sibling { handle value; sibling(const handle &value) : value(value.ptr()) { } }; 345522Snate@binkert.org 35955SN/A/// Annotation indicating that a class derives from another given type 365522Snate@binkert.orgtemplate <typename T> struct base { 37955SN/A PYBIND11_DEPRECATED("base<T>() was deprecated in favor of specifying 'T' as a template argument to class_") 385522Snate@binkert.org base() { } 394202Sbinkertn@umich.edu}; 405742Snate@binkert.org 41955SN/A/// Keep patient alive while nurse lives 424381Sbinkertn@umich.edutemplate <int Nurse, int Patient> struct keep_alive { }; 434381Sbinkertn@umich.edu 448334Snate@binkert.org/// Annotation indicating that a class is involved in a multiple inheritance relationship 45955SN/Astruct multiple_inheritance { }; 46955SN/A 474202Sbinkertn@umich.edu/// Annotation which enables dynamic attributes, i.e. adds `__dict__` to a class 48955SN/Astruct dynamic_attr { }; 494382Sbinkertn@umich.edu 504382Sbinkertn@umich.edu/// Annotation to mark enums as an arithmetic type 514382Sbinkertn@umich.edustruct arithmetic { }; 526654Snate@binkert.org 535517Snate@binkert.orgNAMESPACE_BEGIN(detail) 548614Sgblack@eecs.umich.edu/* Forward declarations */ 557674Snate@binkert.orgenum op_id : int; 566143Snate@binkert.orgenum op_type : int; 576143Snate@binkert.orgstruct undefined_t; 586143Snate@binkert.orgtemplate <op_id id, op_type ot, typename L = undefined_t, typename R = undefined_t> struct op_; 598233Snate@binkert.orgtemplate <typename... Args> struct init; 608233Snate@binkert.orgtemplate <typename... Args> struct init_alias; 618233Snate@binkert.orginline void keep_alive_impl(int Nurse, int Patient, handle args, handle ret); 628233Snate@binkert.org 638233Snate@binkert.org/// Internal data structure which holds metadata about a keyword argument 648334Snate@binkert.orgstruct argument_record { 658334Snate@binkert.org const char *name; ///< Argument name 668233Snate@binkert.org const char *descr; ///< Human-readable version of the argument value 678233Snate@binkert.org handle value; ///< Associated Python object 688233Snate@binkert.org 698233Snate@binkert.org argument_record(const char *name, const char *descr, handle value) 708233Snate@binkert.org : name(name), descr(descr), value(value) { } 718233Snate@binkert.org}; 726143Snate@binkert.org 738233Snate@binkert.org/// Internal data structure which holds metadata about a bound function (signature, overloads, etc.) 748233Snate@binkert.orgstruct function_record { 758233Snate@binkert.org function_record() 766143Snate@binkert.org : is_constructor(false), is_stateless(false), is_operator(false), 776143Snate@binkert.org has_args(false), has_kwargs(false), is_method(false) { } 786143Snate@binkert.org 796143Snate@binkert.org /// Function name 808233Snate@binkert.org char *name = nullptr; /* why no C++ strings? They generate heavier code.. */ 818233Snate@binkert.org 828233Snate@binkert.org // User-specified documentation string 836143Snate@binkert.org char *doc = nullptr; 848233Snate@binkert.org 858233Snate@binkert.org /// Human-readable version of the function signature 868233Snate@binkert.org char *signature = nullptr; 878233Snate@binkert.org 886143Snate@binkert.org /// List of registered keyword arguments 896143Snate@binkert.org std::vector<argument_record> args; 906143Snate@binkert.org 914762Snate@binkert.org /// Pointer to lambda function which converts arguments and performs the actual call 926143Snate@binkert.org handle (*impl) (function_record *, handle, handle, handle) = nullptr; 938233Snate@binkert.org 948233Snate@binkert.org /// Storage for the wrapped function pointer and captured data, if any 958233Snate@binkert.org void *data[3] = { }; 968233Snate@binkert.org 978233Snate@binkert.org /// Pointer to custom destructor for 'data' (if needed) 986143Snate@binkert.org void (*free_data) (function_record *ptr) = nullptr; 998233Snate@binkert.org 1008233Snate@binkert.org /// Return value policy associated with this function 1018233Snate@binkert.org return_value_policy policy = return_value_policy::automatic; 1028233Snate@binkert.org 1036143Snate@binkert.org /// True if name == '__init__' 1046143Snate@binkert.org bool is_constructor : 1; 1056143Snate@binkert.org 1066143Snate@binkert.org /// True if this is a stateless function pointer 1076143Snate@binkert.org bool is_stateless : 1; 1086143Snate@binkert.org 1096143Snate@binkert.org /// True if this is an operator (__add__), etc. 1106143Snate@binkert.org bool is_operator : 1; 1116143Snate@binkert.org 1127065Snate@binkert.org /// True if the function has a '*args' argument 1136143Snate@binkert.org bool has_args : 1; 1148233Snate@binkert.org 1158233Snate@binkert.org /// True if the function has a '**kwargs' argument 1168233Snate@binkert.org bool has_kwargs : 1; 1178233Snate@binkert.org 1188233Snate@binkert.org /// True if this is a method 1198233Snate@binkert.org bool is_method : 1; 1208233Snate@binkert.org 1218233Snate@binkert.org /// Number of arguments 1228233Snate@binkert.org uint16_t nargs; 1238233Snate@binkert.org 1248233Snate@binkert.org /// Python method object 1258233Snate@binkert.org PyMethodDef *def = nullptr; 1268233Snate@binkert.org 1278233Snate@binkert.org /// Python handle to the parent scope (a class or a module) 1288233Snate@binkert.org handle scope; 1298233Snate@binkert.org 1308233Snate@binkert.org /// Python handle to the sibling function representing an overload chain 1318233Snate@binkert.org handle sibling; 1328233Snate@binkert.org 1338233Snate@binkert.org /// Pointer to next overload 1348233Snate@binkert.org function_record *next = nullptr; 1358233Snate@binkert.org}; 1368233Snate@binkert.org 1378233Snate@binkert.org/// Special data structure which (temporarily) holds metadata about a bound class 1388233Snate@binkert.orgstruct type_record { 1398233Snate@binkert.org PYBIND11_NOINLINE type_record() { } 1408233Snate@binkert.org 1418233Snate@binkert.org /// Handle to the parent scope 1428233Snate@binkert.org handle scope; 1438233Snate@binkert.org 1448233Snate@binkert.org /// Name of the class 1456143Snate@binkert.org const char *name = nullptr; 1466143Snate@binkert.org 1476143Snate@binkert.org // Pointer to RTTI type_info data structure 1486143Snate@binkert.org const std::type_info *type = nullptr; 1496143Snate@binkert.org 1506143Snate@binkert.org /// How large is the underlying C++ type? 1516143Snate@binkert.org size_t type_size = 0; 1526143Snate@binkert.org 1536143Snate@binkert.org /// How large is pybind11::instance<type>? 1548913Sandreas.hansson@arm.com size_t instance_size = 0; 1558233Snate@binkert.org 1568233Snate@binkert.org /// Function pointer to class_<..>::init_holder 1576143Snate@binkert.org void (*init_holder)(PyObject *, const void *) = nullptr; 1586143Snate@binkert.org 1596143Snate@binkert.org /// Function pointer to class_<..>::dealloc 1606143Snate@binkert.org void (*dealloc)(PyObject *) = nullptr; 1616143Snate@binkert.org 1625522Snate@binkert.org /// List of base classes of the newly created type 1636143Snate@binkert.org list bases; 1646143Snate@binkert.org 1656143Snate@binkert.org /// Optional docstring 1666143Snate@binkert.org const char *doc = nullptr; 1678233Snate@binkert.org 1688233Snate@binkert.org /// Multiple inheritance marker 1698233Snate@binkert.org bool multiple_inheritance = false; 1706143Snate@binkert.org 1716143Snate@binkert.org /// Does the class manage a __dict__? 1726143Snate@binkert.org bool dynamic_attr = false; 1736143Snate@binkert.org 1745522Snate@binkert.org PYBIND11_NOINLINE void add_base(const std::type_info *base, void *(*caster)(void *)) { 1755522Snate@binkert.org auto base_info = detail::get_type_info(*base, false); 1765522Snate@binkert.org if (!base_info) { 1775522Snate@binkert.org std::string tname(base->name()); 1785604Snate@binkert.org detail::clean_type_id(tname); 1795604Snate@binkert.org pybind11_fail("generic_type: type \"" + std::string(name) + 1806143Snate@binkert.org "\" referenced unknown base type \"" + tname + "\""); 1816143Snate@binkert.org } 1824762Snate@binkert.org 1834762Snate@binkert.org bases.append((PyObject *) base_info->type); 1846143Snate@binkert.org 1856727Ssteve.reinhardt@amd.com if (base_info->type->tp_dictoffset != 0) 1866727Ssteve.reinhardt@amd.com dynamic_attr = true; 1876727Ssteve.reinhardt@amd.com 1884762Snate@binkert.org if (caster) 1896143Snate@binkert.org base_info->implicit_casts.push_back(std::make_pair(type, caster)); 1906143Snate@binkert.org } 1916143Snate@binkert.org}; 1926143Snate@binkert.org 1936727Ssteve.reinhardt@amd.com/** 1946143Snate@binkert.org * Partial template specializations to process custom attributes provided to 1957674Snate@binkert.org * cpp_function_ and class_. These are either used to initialize the respective 1967674Snate@binkert.org * fields in the type_record and function_record data structures or executed at 1975604Snate@binkert.org * runtime to deal with custom call policies (e.g. keep_alive). 1986143Snate@binkert.org */ 1996143Snate@binkert.orgtemplate <typename T, typename SFINAE = void> struct process_attribute; 2006143Snate@binkert.org 2014762Snate@binkert.orgtemplate <typename T> struct process_attribute_default { 2026143Snate@binkert.org /// Default implementation: do nothing 2034762Snate@binkert.org static void init(const T &, function_record *) { } 2044762Snate@binkert.org static void init(const T &, type_record *) { } 2054762Snate@binkert.org static void precall(handle) { } 2066143Snate@binkert.org static void postcall(handle, handle) { } 2076143Snate@binkert.org}; 2084762Snate@binkert.org 2098233Snate@binkert.org/// Process an attribute specifying the function's name 2108233Snate@binkert.orgtemplate <> struct process_attribute<name> : process_attribute_default<name> { 2118233Snate@binkert.org static void init(const name &n, function_record *r) { r->name = const_cast<char *>(n.value); } 2128233Snate@binkert.org}; 2136143Snate@binkert.org 2146143Snate@binkert.org/// Process an attribute specifying the function's docstring 2154762Snate@binkert.orgtemplate <> struct process_attribute<doc> : process_attribute_default<doc> { 2166143Snate@binkert.org static void init(const doc &n, function_record *r) { r->doc = const_cast<char *>(n.value); } 2174762Snate@binkert.org}; 2186143Snate@binkert.org 2194762Snate@binkert.org/// Process an attribute specifying the function's docstring (provided as a C-style string) 2206143Snate@binkert.orgtemplate <> struct process_attribute<const char *> : process_attribute_default<const char *> { 2218233Snate@binkert.org static void init(const char *d, function_record *r) { r->doc = const_cast<char *>(d); } 2228233Snate@binkert.org static void init(const char *d, type_record *r) { r->doc = const_cast<char *>(d); } 2238233Snate@binkert.org}; 2246143Snate@binkert.orgtemplate <> struct process_attribute<char *> : process_attribute<const char *> { }; 2256143Snate@binkert.org 2266143Snate@binkert.org/// Process an attribute indicating the function's return value policy 2276143Snate@binkert.orgtemplate <> struct process_attribute<return_value_policy> : process_attribute_default<return_value_policy> { 2286143Snate@binkert.org static void init(const return_value_policy &p, function_record *r) { r->policy = p; } 2296143Snate@binkert.org}; 2306143Snate@binkert.org 2316143Snate@binkert.org/// Process an attribute which indicates that this is an overloaded function associated with a given sibling 2328233Snate@binkert.orgtemplate <> struct process_attribute<sibling> : process_attribute_default<sibling> { 2338233Snate@binkert.org static void init(const sibling &s, function_record *r) { r->sibling = s.value; } 234955SN/A}; 2358235Snate@binkert.org 2368235Snate@binkert.org/// Process an attribute which indicates that this function is a method 2376143Snate@binkert.orgtemplate <> struct process_attribute<is_method> : process_attribute_default<is_method> { 2388235Snate@binkert.org static void init(const is_method &s, function_record *r) { r->is_method = true; r->scope = s.class_; } 2398235Snate@binkert.org}; 2408235Snate@binkert.org 2418235Snate@binkert.org/// Process an attribute which indicates the parent scope of a method 2428235Snate@binkert.orgtemplate <> struct process_attribute<scope> : process_attribute_default<scope> { 2438235Snate@binkert.org static void init(const scope &s, function_record *r) { r->scope = s.value; } 2448235Snate@binkert.org}; 2458235Snate@binkert.org 2468235Snate@binkert.org/// Process an attribute which indicates that this function is an operator 2478235Snate@binkert.orgtemplate <> struct process_attribute<is_operator> : process_attribute_default<is_operator> { 2488235Snate@binkert.org static void init(const is_operator &, function_record *r) { r->is_operator = true; } 2498235Snate@binkert.org}; 2508235Snate@binkert.org 2518235Snate@binkert.org/// Process a keyword argument attribute (*without* a default value) 2528235Snate@binkert.orgtemplate <> struct process_attribute<arg> : process_attribute_default<arg> { 2538235Snate@binkert.org static void init(const arg &a, function_record *r) { 2548235Snate@binkert.org if (r->is_method && r->args.empty()) 2555584Snate@binkert.org r->args.emplace_back("self", nullptr, handle()); 2564382Sbinkertn@umich.edu r->args.emplace_back(a.name, nullptr, handle()); 2574202Sbinkertn@umich.edu } 2584382Sbinkertn@umich.edu}; 2594382Sbinkertn@umich.edu 2604382Sbinkertn@umich.edu/// Process a keyword argument attribute (*with* a default value) 2615584Snate@binkert.orgtemplate <> struct process_attribute<arg_v> : process_attribute_default<arg_v> { 2624382Sbinkertn@umich.edu static void init(const arg_v &a, function_record *r) { 2634382Sbinkertn@umich.edu if (r->is_method && r->args.empty()) 2644382Sbinkertn@umich.edu r->args.emplace_back("self", nullptr, handle()); 2658232Snate@binkert.org 2665192Ssaidi@eecs.umich.edu if (!a.value) { 2678232Snate@binkert.org#if !defined(NDEBUG) 2688232Snate@binkert.org auto descr = "'" + std::string(a.name) + ": " + a.type + "'"; 2698232Snate@binkert.org if (r->is_method) { 2705192Ssaidi@eecs.umich.edu if (r->name) 2718232Snate@binkert.org descr += " in method '" + (std::string) str(r->scope) + "." + (std::string) r->name + "'"; 2725192Ssaidi@eecs.umich.edu else 2735799Snate@binkert.org descr += " in method of '" + (std::string) str(r->scope) + "'"; 2748232Snate@binkert.org } else if (r->name) { 2755192Ssaidi@eecs.umich.edu descr += " in function named '" + (std::string) r->name + "'"; 2765192Ssaidi@eecs.umich.edu } 2775192Ssaidi@eecs.umich.edu pybind11_fail("arg(): could not convert default keyword argument " 2788232Snate@binkert.org + descr + " into a Python object (type not registered yet?)"); 2795192Ssaidi@eecs.umich.edu#else 2808232Snate@binkert.org pybind11_fail("arg(): could not convert default keyword argument " 2815192Ssaidi@eecs.umich.edu "into a Python object (type not registered yet?). " 2825192Ssaidi@eecs.umich.edu "Compile in debug mode for more information."); 2835192Ssaidi@eecs.umich.edu#endif 2845192Ssaidi@eecs.umich.edu } 2854382Sbinkertn@umich.edu r->args.emplace_back(a.name, a.descr, a.value.inc_ref()); 2864382Sbinkertn@umich.edu } 2874382Sbinkertn@umich.edu}; 2882667Sstever@eecs.umich.edu 2892667Sstever@eecs.umich.edu/// Process a parent class attribute 2902667Sstever@eecs.umich.edutemplate <typename T> 2912667Sstever@eecs.umich.edustruct process_attribute<T, enable_if_t<is_pyobject<T>::value>> : process_attribute_default<handle> { 2922667Sstever@eecs.umich.edu static void init(const handle &h, type_record *r) { r->bases.append(h); } 2932667Sstever@eecs.umich.edu}; 2945742Snate@binkert.org 2955742Snate@binkert.org/// Process a parent class attribute (deprecated, does not support multiple inheritance) 2965742Snate@binkert.orgtemplate <typename T> 2975793Snate@binkert.orgstruct process_attribute<base<T>> : process_attribute_default<base<T>> { 2988334Snate@binkert.org static void init(const base<T> &, type_record *r) { r->add_base(&typeid(T), nullptr); } 2995793Snate@binkert.org}; 3005793Snate@binkert.org 3015793Snate@binkert.org/// Process a multiple inheritance attribute 3024382Sbinkertn@umich.edutemplate <> 3034762Snate@binkert.orgstruct process_attribute<multiple_inheritance> : process_attribute_default<multiple_inheritance> { 3045344Sstever@gmail.com static void init(const multiple_inheritance &, type_record *r) { r->multiple_inheritance = true; } 3054382Sbinkertn@umich.edu}; 3065341Sstever@gmail.com 3075742Snate@binkert.orgtemplate <> 3085742Snate@binkert.orgstruct process_attribute<dynamic_attr> : process_attribute_default<dynamic_attr> { 3095742Snate@binkert.org static void init(const dynamic_attr &, type_record *r) { r->dynamic_attr = true; } 3105742Snate@binkert.org}; 3115742Snate@binkert.org 3124762Snate@binkert.org 3135742Snate@binkert.org/// Process an 'arithmetic' attribute for enums (does nothing here) 3145742Snate@binkert.orgtemplate <> 3157722Sgblack@eecs.umich.edustruct process_attribute<arithmetic> : process_attribute_default<arithmetic> {}; 3165742Snate@binkert.org 3175742Snate@binkert.org/*** 3185742Snate@binkert.org * Process a keep_alive call policy -- invokes keep_alive_impl during the 3195742Snate@binkert.org * pre-call handler if both Nurse, Patient != 0 and use the post-call handler 3208242Sbradley.danofsky@amd.com * otherwise 3218242Sbradley.danofsky@amd.com */ 3228242Sbradley.danofsky@amd.comtemplate <int Nurse, int Patient> struct process_attribute<keep_alive<Nurse, Patient>> : public process_attribute_default<keep_alive<Nurse, Patient>> { 3238242Sbradley.danofsky@amd.com template <int N = Nurse, int P = Patient, enable_if_t<N != 0 && P != 0, int> = 0> 3245341Sstever@gmail.com static void precall(handle args) { keep_alive_impl(Nurse, Patient, args, handle()); } 3255742Snate@binkert.org template <int N = Nurse, int P = Patient, enable_if_t<N != 0 && P != 0, int> = 0> 3267722Sgblack@eecs.umich.edu static void postcall(handle, handle) { } 3274773Snate@binkert.org template <int N = Nurse, int P = Patient, enable_if_t<N == 0 || P == 0, int> = 0> 3286108Snate@binkert.org static void precall(handle) { } 3291858SN/A template <int N = Nurse, int P = Patient, enable_if_t<N == 0 || P == 0, int> = 0> 3301085SN/A static void postcall(handle args, handle ret) { keep_alive_impl(Nurse, Patient, args, ret); } 3316658Snate@binkert.org}; 3326658Snate@binkert.org 3337673Snate@binkert.org/// Recursively iterate over variadic template arguments 3346658Snate@binkert.orgtemplate <typename... Args> struct process_attributes { 3356658Snate@binkert.org static void init(const Args&... args, function_record *r) { 3366658Snate@binkert.org int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::init(args, r), 0) ... }; 3376658Snate@binkert.org ignore_unused(unused); 3386658Snate@binkert.org } 3396658Snate@binkert.org static void init(const Args&... args, type_record *r) { 3406658Snate@binkert.org int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::init(args, r), 0) ... }; 3417673Snate@binkert.org ignore_unused(unused); 3427673Snate@binkert.org } 3437673Snate@binkert.org static void precall(handle fn_args) { 3447673Snate@binkert.org int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::precall(fn_args), 0) ... }; 3457673Snate@binkert.org ignore_unused(unused); 3467673Snate@binkert.org } 3477673Snate@binkert.org static void postcall(handle fn_args, handle fn_ret) { 3486658Snate@binkert.org int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::postcall(fn_args, fn_ret), 0) ... }; 3497673Snate@binkert.org ignore_unused(unused); 3507673Snate@binkert.org } 3517673Snate@binkert.org}; 3527673Snate@binkert.org 3537673Snate@binkert.org/// Check the number of named arguments at compile time 3547673Snate@binkert.orgtemplate <typename... Extra, 3557673Snate@binkert.org size_t named = constexpr_sum(std::is_base_of<arg, Extra>::value...), 3567673Snate@binkert.org size_t self = constexpr_sum(std::is_same<is_method, Extra>::value...)> 3577673Snate@binkert.orgconstexpr bool expected_num_args(size_t nargs) { 3587673Snate@binkert.org return named == 0 || (self + named) == nargs; 3596658Snate@binkert.org} 3607756SAli.Saidi@ARM.com 3617816Ssteve.reinhardt@amd.comNAMESPACE_END(detail) 3626658Snate@binkert.orgNAMESPACE_END(pybind11) 3634382Sbinkertn@umich.edu