mirror of
https://github.com/pybind/pybind11.git
synced 2026-05-24 06:45:03 +00:00
set __module__ attribute of functions (fixes #95)
This commit is contained in:
@@ -36,6 +36,9 @@ template <typename T> arg_t<T> arg::operator=(const T &value) { return arg_t<T>(
|
||||
/// Annotation for methods
|
||||
struct is_method { handle class_; is_method(const handle &c) : class_(c) { } };
|
||||
|
||||
/// Annotation for parent scope
|
||||
struct scope { handle value; scope(const handle &s) : value(s) { } };
|
||||
|
||||
/// Annotation for documentation
|
||||
struct doc { const char *value; doc(const char *value) : value(value) { } };
|
||||
|
||||
@@ -105,6 +108,9 @@ struct function_record {
|
||||
/// Python handle to the associated class (if this is method)
|
||||
handle class_;
|
||||
|
||||
/// Python handle to the parent scope (a class or a module)
|
||||
handle scope;
|
||||
|
||||
/// Python handle to the sibling function representing an overload chain
|
||||
handle sibling;
|
||||
|
||||
@@ -190,9 +196,15 @@ template <> struct process_attribute<sibling> : process_attribute_default<siblin
|
||||
|
||||
/// Process an attribute which indicates that this function is a method
|
||||
template <> struct process_attribute<is_method> : process_attribute_default<is_method> {
|
||||
static void init(const is_method &s, function_record *r) { r->class_ = s.class_; }
|
||||
static void init(const is_method &s, function_record *r) { r->class_ = s.class_; r->scope = s.class_; }
|
||||
};
|
||||
|
||||
/// Process an attribute which indicates the parent scope of a method
|
||||
template <> struct process_attribute<scope> : process_attribute_default<scope> {
|
||||
static void init(const scope &s, function_record *r) { r->scope = s.value; }
|
||||
};
|
||||
|
||||
|
||||
/// Process a keyword argument attribute (*without* a default value)
|
||||
template <> struct process_attribute<arg> : process_attribute_default<arg> {
|
||||
static void init(const arg &a, function_record *r) {
|
||||
|
||||
@@ -263,10 +263,19 @@ protected:
|
||||
rec->def->ml_name = rec->name;
|
||||
rec->def->ml_meth = reinterpret_cast<PyCFunction>(*dispatcher);
|
||||
rec->def->ml_flags = METH_VARARGS | METH_KEYWORDS;
|
||||
|
||||
capsule rec_capsule(rec, [](PyObject *o) {
|
||||
destruct((detail::function_record *) PyCapsule_GetPointer(o, nullptr));
|
||||
});
|
||||
m_ptr = PyCFunction_New(rec->def, rec_capsule.ptr());
|
||||
|
||||
object scope_module;
|
||||
if (rec->scope) {
|
||||
scope_module = (object) rec->scope.attr("__module__");
|
||||
if (!scope_module)
|
||||
scope_module = (object) rec->scope.attr("__name__");
|
||||
}
|
||||
|
||||
m_ptr = PyCFunction_NewEx(rec->def, rec_capsule.ptr(), scope_module.ptr());
|
||||
if (!m_ptr)
|
||||
pybind11_fail("cpp_function::cpp_function(): Could not allocate function object");
|
||||
} else {
|
||||
@@ -467,7 +476,7 @@ public:
|
||||
template <typename Func, typename... Extra>
|
||||
module &def(const char *name_, Func &&f, const Extra& ... extra) {
|
||||
cpp_function func(std::forward<Func>(f), name(name_),
|
||||
sibling((handle) attr(name_)), extra...);
|
||||
sibling((handle) attr(name_)), scope(*this), extra...);
|
||||
/* PyModule_AddObject steals a reference to 'func' */
|
||||
PyModule_AddObject(ptr(), name_, func.inc_ref().ptr());
|
||||
return *this;
|
||||
@@ -742,26 +751,26 @@ public:
|
||||
template <typename Func, typename... Extra> class_ &
|
||||
def_static(const char *name_, Func f, const Extra&... extra) {
|
||||
cpp_function cf(std::forward<Func>(f), name(name_),
|
||||
sibling(attr(name_)), extra...);
|
||||
sibling(attr(name_)), scope(*this), extra...);
|
||||
attr(cf.name()) = cf;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <detail::op_id id, detail::op_type ot, typename L, typename R, typename... Extra>
|
||||
class_ &def(const detail::op_<id, ot, L, R> &op, const Extra&... extra) {
|
||||
op.template execute<type>(*this, extra...);
|
||||
op.template execute<type>(*this, is_method(*this), extra...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <detail::op_id id, detail::op_type ot, typename L, typename R, typename... Extra>
|
||||
class_ & def_cast(const detail::op_<id, ot, L, R> &op, const Extra&... extra) {
|
||||
op.template execute_cast<type>(*this, extra...);
|
||||
op.template execute_cast<type>(*this, is_method(*this), extra...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename... Args, typename... Extra>
|
||||
class_ &def(const detail::init<Args...> &init, const Extra&... extra) {
|
||||
init.template execute<type>(*this, extra...);
|
||||
init.template execute<type>(*this, is_method(*this), extra...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -800,8 +809,8 @@ public:
|
||||
template <typename D, typename... Extra>
|
||||
class_ &def_readwrite_static(const char *name, D *pm, const Extra& ...extra) {
|
||||
cpp_function fget([pm](object) -> const D &{ return *pm; },
|
||||
return_value_policy::reference_internal, extra...),
|
||||
fset([pm](object, const D &value) { *pm = value; }, extra...);
|
||||
return_value_policy::reference_internal, scope(*this), extra...),
|
||||
fset([pm](object, const D &value) { *pm = value; }, scope(*this), extra...);
|
||||
def_property_static(name, fget, fset);
|
||||
return *this;
|
||||
}
|
||||
@@ -809,7 +818,7 @@ public:
|
||||
template <typename D, typename... Extra>
|
||||
class_ &def_readonly_static(const char *name, const D *pm, const Extra& ...extra) {
|
||||
cpp_function fget([pm](object) -> const D &{ return *pm; },
|
||||
return_value_policy::reference_internal, extra...);
|
||||
return_value_policy::reference_internal, scope(*this), extra...);
|
||||
def_property_readonly_static(name, fget);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user