Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
gaoqiong
pybind11
Commits
024932b3
Commit
024932b3
authored
Aug 20, 2017
by
Dean Moldovan
Browse files
Move everything related to `internals` into a separate detail header
parent
3271fecf
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
235 additions
and
210 deletions
+235
-210
CMakeLists.txt
CMakeLists.txt
+1
-0
include/pybind11/cast.h
include/pybind11/cast.h
+1
-102
include/pybind11/detail/common.h
include/pybind11/detail/common.h
+0
-108
include/pybind11/detail/internals.h
include/pybind11/detail/internals.h
+232
-0
setup.py
setup.py
+1
-0
No files found.
CMakeLists.txt
View file @
024932b3
...
...
@@ -40,6 +40,7 @@ set(PYBIND11_HEADERS
include/pybind11/detail/common.h
include/pybind11/detail/descr.h
include/pybind11/detail/init.h
include/pybind11/detail/internals.h
include/pybind11/detail/typeid.h
include/pybind11/attr.h
include/pybind11/buffer_info.h
...
...
include/pybind11/cast.h
View file @
024932b3
...
...
@@ -13,6 +13,7 @@
#include "pytypes.h"
#include "detail/typeid.h"
#include "detail/descr.h"
#include "detail/internals.h"
#include <array>
#include <limits>
#include <tuple>
...
...
@@ -32,108 +33,6 @@
NAMESPACE_BEGIN
(
PYBIND11_NAMESPACE
)
NAMESPACE_BEGIN
(
detail
)
// Forward declarations:
inline
PyTypeObject
*
make_static_property_type
();
inline
PyTypeObject
*
make_default_metaclass
();
inline
PyObject
*
make_object_base_type
(
PyTypeObject
*
metaclass
);
struct
value_and_holder
;
/// Additional type information which does not fit into the PyTypeObject
struct
type_info
{
PyTypeObject
*
type
;
const
std
::
type_info
*
cpptype
;
size_t
type_size
,
holder_size_in_ptrs
;
void
*
(
*
operator_new
)(
size_t
);
void
(
*
init_instance
)(
instance
*
,
const
void
*
);
void
(
*
dealloc
)(
value_and_holder
&
v_h
);
std
::
vector
<
PyObject
*
(
*
)(
PyObject
*
,
PyTypeObject
*
)
>
implicit_conversions
;
std
::
vector
<
std
::
pair
<
const
std
::
type_info
*
,
void
*
(
*
)(
void
*
)
>>
implicit_casts
;
std
::
vector
<
bool
(
*
)(
PyObject
*
,
void
*&
)
>
*
direct_conversions
;
buffer_info
*
(
*
get_buffer
)(
PyObject
*
,
void
*
)
=
nullptr
;
void
*
get_buffer_data
=
nullptr
;
void
*
(
*
module_local_load
)(
PyObject
*
,
const
type_info
*
)
=
nullptr
;
/* A simple type never occurs as a (direct or indirect) parent
* of a class that makes use of multiple inheritance */
bool
simple_type
:
1
;
/* True if there is no multiple inheritance in this type's inheritance tree */
bool
simple_ancestors
:
1
;
/* for base vs derived holder_type checks */
bool
default_holder
:
1
;
/* true if this is a type registered with py::module_local */
bool
module_local
:
1
;
};
PYBIND11_NOINLINE
inline
internals
*&
get_internals_ptr
()
{
static
internals
*
internals_ptr
=
nullptr
;
return
internals_ptr
;
}
PYBIND11_NOINLINE
inline
internals
&
get_internals
()
{
internals
*&
internals_ptr
=
get_internals_ptr
();
if
(
internals_ptr
)
return
*
internals_ptr
;
handle
builtins
(
PyEval_GetBuiltins
());
const
char
*
id
=
PYBIND11_INTERNALS_ID
;
if
(
builtins
.
contains
(
id
)
&&
isinstance
<
capsule
>
(
builtins
[
id
]))
{
internals_ptr
=
*
static_cast
<
internals
**>
(
capsule
(
builtins
[
id
]));
// We loaded builtins through python's builtins, which means that our error_already_set and
// builtin_exception may be different local classes than the ones set up in the initial
// exception translator, below, so add another for our local exception classes.
//
// stdlibc++ doesn't require this (types there are identified only by name)
#if !defined(__GLIBCXX__)
internals_ptr
->
registered_exception_translators
.
push_front
(
[](
std
::
exception_ptr
p
)
->
void
{
try
{
if
(
p
)
std
::
rethrow_exception
(
p
);
}
catch
(
error_already_set
&
e
)
{
e
.
restore
();
return
;
}
catch
(
const
builtin_exception
&
e
)
{
e
.
set_error
();
return
;
}
}
);
#endif
}
else
{
internals_ptr
=
new
internals
();
#if defined(WITH_THREAD)
PyEval_InitThreads
();
PyThreadState
*
tstate
=
PyThreadState_Get
();
internals_ptr
->
tstate
=
PyThread_create_key
();
PyThread_set_key_value
(
internals_ptr
->
tstate
,
tstate
);
internals_ptr
->
istate
=
tstate
->
interp
;
#endif
builtins
[
id
]
=
capsule
(
&
internals_ptr
);
internals_ptr
->
registered_exception_translators
.
push_front
(
[](
std
::
exception_ptr
p
)
->
void
{
try
{
if
(
p
)
std
::
rethrow_exception
(
p
);
}
catch
(
error_already_set
&
e
)
{
e
.
restore
();
return
;
}
catch
(
const
builtin_exception
&
e
)
{
e
.
set_error
();
return
;
}
catch
(
const
std
::
bad_alloc
&
e
)
{
PyErr_SetString
(
PyExc_MemoryError
,
e
.
what
());
return
;
}
catch
(
const
std
::
domain_error
&
e
)
{
PyErr_SetString
(
PyExc_ValueError
,
e
.
what
());
return
;
}
catch
(
const
std
::
invalid_argument
&
e
)
{
PyErr_SetString
(
PyExc_ValueError
,
e
.
what
());
return
;
}
catch
(
const
std
::
length_error
&
e
)
{
PyErr_SetString
(
PyExc_ValueError
,
e
.
what
());
return
;
}
catch
(
const
std
::
out_of_range
&
e
)
{
PyErr_SetString
(
PyExc_IndexError
,
e
.
what
());
return
;
}
catch
(
const
std
::
range_error
&
e
)
{
PyErr_SetString
(
PyExc_ValueError
,
e
.
what
());
return
;
}
catch
(
const
std
::
exception
&
e
)
{
PyErr_SetString
(
PyExc_RuntimeError
,
e
.
what
());
return
;
}
catch
(...)
{
PyErr_SetString
(
PyExc_RuntimeError
,
"Caught an unknown exception!"
);
return
;
}
}
);
internals_ptr
->
static_property_type
=
make_static_property_type
();
internals_ptr
->
default_metaclass
=
make_default_metaclass
();
internals_ptr
->
instance_base
=
make_object_base_type
(
internals_ptr
->
default_metaclass
);
}
return
*
internals_ptr
;
}
// Works like internals.registered_types_cpp, but for module-local registered types:
PYBIND11_NOINLINE
inline
type_map
<
void
*>
&
registered_local_types_cpp
()
{
static
type_map
<
void
*>
locals
{};
return
locals
;
}
/// A life support system for temporary objects created by `type_caster::load()`.
/// Adding a patient will keep it alive up until the enclosing function returns.
...
...
include/pybind11/detail/common.h
View file @
024932b3
...
...
@@ -205,8 +205,6 @@ extern "C" {
#define PYBIND11_TRY_NEXT_OVERLOAD ((PyObject *) 1) // special failure return code
#define PYBIND11_STRINGIFY(x) #x
#define PYBIND11_TOSTRING(x) PYBIND11_STRINGIFY(x)
#define PYBIND11_INTERNALS_ID "__pybind11_" \
PYBIND11_TOSTRING(PYBIND11_VERSION_MAJOR) "_" PYBIND11_TOSTRING(PYBIND11_VERSION_MINOR) "__"
/** \rst
***Deprecated in favor of PYBIND11_MODULE***
...
...
@@ -442,73 +440,6 @@ struct instance {
static_assert
(
std
::
is_standard_layout
<
instance
>::
value
,
"Internal error: `pybind11::detail::instance` is not standard layout!"
);
struct
overload_hash
{
inline
size_t
operator
()(
const
std
::
pair
<
const
PyObject
*
,
const
char
*>&
v
)
const
{
size_t
value
=
std
::
hash
<
const
void
*>
()(
v
.
first
);
value
^=
std
::
hash
<
const
void
*>
()(
v
.
second
)
+
0x9e3779b9
+
(
value
<<
6
)
+
(
value
>>
2
);
return
value
;
}
};
// Python loads modules by default with dlopen with the RTLD_LOCAL flag; under libc++ and possibly
// other stls, this means `typeid(A)` from one module won't equal `typeid(A)` from another module
// even when `A` is the same, non-hidden-visibility type (e.g. from a common include). Under
// stdlibc++, this doesn't happen: equality and the type_index hash are based on the type name,
// which works. If not under a known-good stl, provide our own name-based hasher and equality
// functions that use the type name.
#if defined(__GLIBCXX__)
inline
bool
same_type
(
const
std
::
type_info
&
lhs
,
const
std
::
type_info
&
rhs
)
{
return
lhs
==
rhs
;
}
using
type_hash
=
std
::
hash
<
std
::
type_index
>
;
using
type_equal_to
=
std
::
equal_to
<
std
::
type_index
>
;
#else
inline
bool
same_type
(
const
std
::
type_info
&
lhs
,
const
std
::
type_info
&
rhs
)
{
return
lhs
.
name
()
==
rhs
.
name
()
||
std
::
strcmp
(
lhs
.
name
(),
rhs
.
name
())
==
0
;
}
struct
type_hash
{
size_t
operator
()(
const
std
::
type_index
&
t
)
const
{
size_t
hash
=
5381
;
const
char
*
ptr
=
t
.
name
();
while
(
auto
c
=
static_cast
<
unsigned
char
>
(
*
ptr
++
))
hash
=
(
hash
*
33
)
^
c
;
return
hash
;
}
};
struct
type_equal_to
{
bool
operator
()(
const
std
::
type_index
&
lhs
,
const
std
::
type_index
&
rhs
)
const
{
return
lhs
.
name
()
==
rhs
.
name
()
||
std
::
strcmp
(
lhs
.
name
(),
rhs
.
name
())
==
0
;
}
};
#endif
template
<
typename
value_type
>
using
type_map
=
std
::
unordered_map
<
std
::
type_index
,
value_type
,
type_hash
,
type_equal_to
>
;
/// Internal data structure used to track registered instances and types
struct
internals
{
type_map
<
void
*>
registered_types_cpp
;
// std::type_index -> type_info
std
::
unordered_map
<
PyTypeObject
*
,
std
::
vector
<
type_info
*>>
registered_types_py
;
// PyTypeObject* -> base type_info(s)
std
::
unordered_multimap
<
const
void
*
,
instance
*>
registered_instances
;
// void * -> instance*
std
::
unordered_set
<
std
::
pair
<
const
PyObject
*
,
const
char
*>
,
overload_hash
>
inactive_overload_cache
;
type_map
<
std
::
vector
<
bool
(
*
)(
PyObject
*
,
void
*&
)
>>
direct_conversions
;
std
::
unordered_map
<
const
PyObject
*
,
std
::
vector
<
PyObject
*>>
patients
;
std
::
forward_list
<
void
(
*
)
(
std
::
exception_ptr
)
>
registered_exception_translators
;
std
::
unordered_map
<
std
::
string
,
void
*>
shared_data
;
// Custom data to be shared across extensions
std
::
vector
<
PyObject
*>
loader_patient_stack
;
// Used by `loader_life_support`
std
::
forward_list
<
std
::
string
>
static_strings
;
// Stores the std::strings backing detail::c_str()
PyTypeObject
*
static_property_type
;
PyTypeObject
*
default_metaclass
;
PyObject
*
instance_base
;
#if defined(WITH_THREAD)
decltype
(
PyThread_create_key
())
tstate
=
0
;
// Usually an int but a long on Cygwin64 with Python 3.x
PyInterpreterState
*
istate
=
nullptr
;
#endif
};
/// Return a reference to the current 'internals' information
inline
internals
&
get_internals
();
/// from __cpp_future__ import (convenient aliases from C++14/17)
#if defined(PYBIND11_CPP14) && (!defined(_MSC_VER) || _MSC_VER >= 1910)
using
std
::
enable_if_t
;
...
...
@@ -716,47 +647,8 @@ using expand_side_effects = bool[];
#define PYBIND11_EXPAND_SIDE_EFFECTS(PATTERN) pybind11::detail::expand_side_effects{ ((PATTERN), void(), false)..., false }
#endif
/// Constructs a std::string with the given arguments, stores it in `internals`, and returns its
/// `c_str()`. Such strings objects have a long storage duration -- the internal strings are only
/// cleared when the program exits or after interpreter shutdown (when embedding), and so are
/// suitable for c-style strings needed by Python internals (such as PyTypeObject's tp_name).
template
<
typename
...
Args
>
const
char
*
c_str
(
Args
&&
...
args
)
{
auto
&
strings
=
get_internals
().
static_strings
;
strings
.
emplace_front
(
std
::
forward
<
Args
>
(
args
)...);
return
strings
.
front
().
c_str
();
}
NAMESPACE_END
(
detail
)
/// Returns a named pointer that is shared among all extension modules (using the same
/// pybind11 version) running in the current interpreter. Names starting with underscores
/// are reserved for internal usage. Returns `nullptr` if no matching entry was found.
inline
PYBIND11_NOINLINE
void
*
get_shared_data
(
const
std
::
string
&
name
)
{
auto
&
internals
=
detail
::
get_internals
();
auto
it
=
internals
.
shared_data
.
find
(
name
);
return
it
!=
internals
.
shared_data
.
end
()
?
it
->
second
:
nullptr
;
}
/// Set the shared data that can be later recovered by `get_shared_data()`.
inline
PYBIND11_NOINLINE
void
*
set_shared_data
(
const
std
::
string
&
name
,
void
*
data
)
{
detail
::
get_internals
().
shared_data
[
name
]
=
data
;
return
data
;
}
/// Returns a typed reference to a shared data entry (by using `get_shared_data()`) if
/// such entry exists. Otherwise, a new object of default-constructible type `T` is
/// added to the shared data under the given name and a reference to it is returned.
template
<
typename
T
>
T
&
get_or_create_shared_data
(
const
std
::
string
&
name
)
{
auto
&
internals
=
detail
::
get_internals
();
auto
it
=
internals
.
shared_data
.
find
(
name
);
T
*
ptr
=
(
T
*
)
(
it
!=
internals
.
shared_data
.
end
()
?
it
->
second
:
nullptr
);
if
(
!
ptr
)
{
ptr
=
new
T
();
internals
.
shared_data
[
name
]
=
ptr
;
}
return
*
ptr
;
}
/// C++ bindings of builtin Python exceptions
class
builtin_exception
:
public
std
::
runtime_error
{
public:
...
...
include/pybind11/detail/internals.h
0 → 100644
View file @
024932b3
/*
pybind11/detail/internals.h: Internal data structure and related functions
Copyright (c) 2017 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/
#pragma once
#include "../pytypes.h"
NAMESPACE_BEGIN
(
PYBIND11_NAMESPACE
)
NAMESPACE_BEGIN
(
detail
)
// Forward declarations
inline
PyTypeObject
*
make_static_property_type
();
inline
PyTypeObject
*
make_default_metaclass
();
inline
PyObject
*
make_object_base_type
(
PyTypeObject
*
metaclass
);
// Python loads modules by default with dlopen with the RTLD_LOCAL flag; under libc++ and possibly
// other STLs, this means `typeid(A)` from one module won't equal `typeid(A)` from another module
// even when `A` is the same, non-hidden-visibility type (e.g. from a common include). Under
// libstdc++, this doesn't happen: equality and the type_index hash are based on the type name,
// which works. If not under a known-good stl, provide our own name-based hash and equality
// functions that use the type name.
#if defined(__GLIBCXX__)
inline
bool
same_type
(
const
std
::
type_info
&
lhs
,
const
std
::
type_info
&
rhs
)
{
return
lhs
==
rhs
;
}
using
type_hash
=
std
::
hash
<
std
::
type_index
>
;
using
type_equal_to
=
std
::
equal_to
<
std
::
type_index
>
;
#else
inline
bool
same_type
(
const
std
::
type_info
&
lhs
,
const
std
::
type_info
&
rhs
)
{
return
lhs
.
name
()
==
rhs
.
name
()
||
std
::
strcmp
(
lhs
.
name
(),
rhs
.
name
())
==
0
;
}
struct
type_hash
{
size_t
operator
()(
const
std
::
type_index
&
t
)
const
{
size_t
hash
=
5381
;
const
char
*
ptr
=
t
.
name
();
while
(
auto
c
=
static_cast
<
unsigned
char
>
(
*
ptr
++
))
hash
=
(
hash
*
33
)
^
c
;
return
hash
;
}
};
struct
type_equal_to
{
bool
operator
()(
const
std
::
type_index
&
lhs
,
const
std
::
type_index
&
rhs
)
const
{
return
lhs
.
name
()
==
rhs
.
name
()
||
std
::
strcmp
(
lhs
.
name
(),
rhs
.
name
())
==
0
;
}
};
#endif
template
<
typename
value_type
>
using
type_map
=
std
::
unordered_map
<
std
::
type_index
,
value_type
,
type_hash
,
type_equal_to
>
;
struct
overload_hash
{
inline
size_t
operator
()(
const
std
::
pair
<
const
PyObject
*
,
const
char
*>&
v
)
const
{
size_t
value
=
std
::
hash
<
const
void
*>
()(
v
.
first
);
value
^=
std
::
hash
<
const
void
*>
()(
v
.
second
)
+
0x9e3779b9
+
(
value
<<
6
)
+
(
value
>>
2
);
return
value
;
}
};
/// Internal data structure used to track registered instances and types.
struct
internals
{
type_map
<
void
*>
registered_types_cpp
;
// std::type_index -> type_info
std
::
unordered_map
<
PyTypeObject
*
,
std
::
vector
<
type_info
*>>
registered_types_py
;
// PyTypeObject* -> base type_info(s)
std
::
unordered_multimap
<
const
void
*
,
instance
*>
registered_instances
;
// void * -> instance*
std
::
unordered_set
<
std
::
pair
<
const
PyObject
*
,
const
char
*>
,
overload_hash
>
inactive_overload_cache
;
type_map
<
std
::
vector
<
bool
(
*
)(
PyObject
*
,
void
*&
)
>>
direct_conversions
;
std
::
unordered_map
<
const
PyObject
*
,
std
::
vector
<
PyObject
*>>
patients
;
std
::
forward_list
<
void
(
*
)
(
std
::
exception_ptr
)
>
registered_exception_translators
;
std
::
unordered_map
<
std
::
string
,
void
*>
shared_data
;
// Custom data to be shared across extensions
std
::
vector
<
PyObject
*>
loader_patient_stack
;
// Used by `loader_life_support`
std
::
forward_list
<
std
::
string
>
static_strings
;
// Stores the std::strings backing detail::c_str()
PyTypeObject
*
static_property_type
;
PyTypeObject
*
default_metaclass
;
PyObject
*
instance_base
;
#if defined(WITH_THREAD)
decltype
(
PyThread_create_key
())
tstate
=
0
;
// Usually an int but a long on Cygwin64 with Python 3.x
PyInterpreterState
*
istate
=
nullptr
;
#endif
};
/// Additional type information which does not fit into the PyTypeObject.
struct
type_info
{
PyTypeObject
*
type
;
const
std
::
type_info
*
cpptype
;
size_t
type_size
,
holder_size_in_ptrs
;
void
*
(
*
operator_new
)(
size_t
);
void
(
*
init_instance
)(
instance
*
,
const
void
*
);
void
(
*
dealloc
)(
value_and_holder
&
v_h
);
std
::
vector
<
PyObject
*
(
*
)(
PyObject
*
,
PyTypeObject
*
)
>
implicit_conversions
;
std
::
vector
<
std
::
pair
<
const
std
::
type_info
*
,
void
*
(
*
)(
void
*
)
>>
implicit_casts
;
std
::
vector
<
bool
(
*
)(
PyObject
*
,
void
*&
)
>
*
direct_conversions
;
buffer_info
*
(
*
get_buffer
)(
PyObject
*
,
void
*
)
=
nullptr
;
void
*
get_buffer_data
=
nullptr
;
void
*
(
*
module_local_load
)(
PyObject
*
,
const
type_info
*
)
=
nullptr
;
/* A simple type never occurs as a (direct or indirect) parent
* of a class that makes use of multiple inheritance */
bool
simple_type
:
1
;
/* True if there is no multiple inheritance in this type's inheritance tree */
bool
simple_ancestors
:
1
;
/* for base vs derived holder_type checks */
bool
default_holder
:
1
;
/* true if this is a type registered with py::module_local */
bool
module_local
:
1
;
};
#define PYBIND11_INTERNALS_ID "__pybind11_" \
PYBIND11_TOSTRING(PYBIND11_VERSION_MAJOR) "_" PYBIND11_TOSTRING(PYBIND11_VERSION_MINOR) "__"
/// Each module locally stores a pointer to the `internals` data. The data
/// itself is shared among modules with the same `PYBIND11_INTERNALS_ID`.
PYBIND11_NOINLINE
inline
internals
*&
get_internals_ptr
()
{
static
internals
*
internals_ptr
=
nullptr
;
return
internals_ptr
;
}
/// Return a reference to the current `internals` data
PYBIND11_NOINLINE
inline
internals
&
get_internals
()
{
auto
*&
internals_ptr
=
get_internals_ptr
();
if
(
internals_ptr
)
return
*
internals_ptr
;
constexpr
auto
*
id
=
PYBIND11_INTERNALS_ID
;
auto
builtins
=
handle
(
PyEval_GetBuiltins
());
if
(
builtins
.
contains
(
id
)
&&
isinstance
<
capsule
>
(
builtins
[
id
]))
{
internals_ptr
=
*
static_cast
<
internals
**>
(
capsule
(
builtins
[
id
]));
// We loaded builtins through python's builtins, which means that our `error_already_set`
// and `builtin_exception` may be different local classes than the ones set up in the
// initial exception translator, below, so add another for our local exception classes.
//
// libstdc++ doesn't require this (types there are identified only by name)
#if !defined(__GLIBCXX__)
internals_ptr
->
registered_exception_translators
.
push_front
(
[](
std
::
exception_ptr
p
)
->
void
{
try
{
if
(
p
)
std
::
rethrow_exception
(
p
);
}
catch
(
error_already_set
&
e
)
{
e
.
restore
();
return
;
}
catch
(
const
builtin_exception
&
e
)
{
e
.
set_error
();
return
;
}
}
);
#endif
}
else
{
internals_ptr
=
new
internals
();
#if defined(WITH_THREAD)
PyEval_InitThreads
();
PyThreadState
*
tstate
=
PyThreadState_Get
();
internals_ptr
->
tstate
=
PyThread_create_key
();
PyThread_set_key_value
(
internals_ptr
->
tstate
,
tstate
);
internals_ptr
->
istate
=
tstate
->
interp
;
#endif
builtins
[
id
]
=
capsule
(
&
internals_ptr
);
internals_ptr
->
registered_exception_translators
.
push_front
(
[](
std
::
exception_ptr
p
)
->
void
{
try
{
if
(
p
)
std
::
rethrow_exception
(
p
);
}
catch
(
error_already_set
&
e
)
{
e
.
restore
();
return
;
}
catch
(
const
builtin_exception
&
e
)
{
e
.
set_error
();
return
;
}
catch
(
const
std
::
bad_alloc
&
e
)
{
PyErr_SetString
(
PyExc_MemoryError
,
e
.
what
());
return
;
}
catch
(
const
std
::
domain_error
&
e
)
{
PyErr_SetString
(
PyExc_ValueError
,
e
.
what
());
return
;
}
catch
(
const
std
::
invalid_argument
&
e
)
{
PyErr_SetString
(
PyExc_ValueError
,
e
.
what
());
return
;
}
catch
(
const
std
::
length_error
&
e
)
{
PyErr_SetString
(
PyExc_ValueError
,
e
.
what
());
return
;
}
catch
(
const
std
::
out_of_range
&
e
)
{
PyErr_SetString
(
PyExc_IndexError
,
e
.
what
());
return
;
}
catch
(
const
std
::
range_error
&
e
)
{
PyErr_SetString
(
PyExc_ValueError
,
e
.
what
());
return
;
}
catch
(
const
std
::
exception
&
e
)
{
PyErr_SetString
(
PyExc_RuntimeError
,
e
.
what
());
return
;
}
catch
(...)
{
PyErr_SetString
(
PyExc_RuntimeError
,
"Caught an unknown exception!"
);
return
;
}
}
);
internals_ptr
->
static_property_type
=
make_static_property_type
();
internals_ptr
->
default_metaclass
=
make_default_metaclass
();
internals_ptr
->
instance_base
=
make_object_base_type
(
internals_ptr
->
default_metaclass
);
}
return
*
internals_ptr
;
}
/// Works like `internals.registered_types_cpp`, but for module-local registered types:
PYBIND11_NOINLINE
inline
type_map
<
void
*>
&
registered_local_types_cpp
()
{
static
type_map
<
void
*>
locals
{};
return
locals
;
}
/// Constructs a std::string with the given arguments, stores it in `internals`, and returns its
/// `c_str()`. Such strings objects have a long storage duration -- the internal strings are only
/// cleared when the program exits or after interpreter shutdown (when embedding), and so are
/// suitable for c-style strings needed by Python internals (such as PyTypeObject's tp_name).
template
<
typename
...
Args
>
const
char
*
c_str
(
Args
&&
...
args
)
{
auto
&
strings
=
get_internals
().
static_strings
;
strings
.
emplace_front
(
std
::
forward
<
Args
>
(
args
)...);
return
strings
.
front
().
c_str
();
}
NAMESPACE_END
(
detail
)
/// Returns a named pointer that is shared among all extension modules (using the same
/// pybind11 version) running in the current interpreter. Names starting with underscores
/// are reserved for internal usage. Returns `nullptr` if no matching entry was found.
inline
PYBIND11_NOINLINE
void
*
get_shared_data
(
const
std
::
string
&
name
)
{
auto
&
internals
=
detail
::
get_internals
();
auto
it
=
internals
.
shared_data
.
find
(
name
);
return
it
!=
internals
.
shared_data
.
end
()
?
it
->
second
:
nullptr
;
}
/// Set the shared data that can be later recovered by `get_shared_data()`.
inline
PYBIND11_NOINLINE
void
*
set_shared_data
(
const
std
::
string
&
name
,
void
*
data
)
{
detail
::
get_internals
().
shared_data
[
name
]
=
data
;
return
data
;
}
/// Returns a typed reference to a shared data entry (by using `get_shared_data()`) if
/// such entry exists. Otherwise, a new object of default-constructible type `T` is
/// added to the shared data under the given name and a reference to it is returned.
template
<
typename
T
>
T
&
get_or_create_shared_data
(
const
std
::
string
&
name
)
{
auto
&
internals
=
detail
::
get_internals
();
auto
it
=
internals
.
shared_data
.
find
(
name
);
T
*
ptr
=
(
T
*
)
(
it
!=
internals
.
shared_data
.
end
()
?
it
->
second
:
nullptr
);
if
(
!
ptr
)
{
ptr
=
new
T
();
internals
.
shared_data
[
name
]
=
ptr
;
}
return
*
ptr
;
}
NAMESPACE_END
(
PYBIND11_NAMESPACE
)
setup.py
View file @
024932b3
...
...
@@ -16,6 +16,7 @@ else:
'include/pybind11/detail/common.h'
,
'include/pybind11/detail/descr.h'
,
'include/pybind11/detail/init.h'
,
'include/pybind11/detail/internals.h'
,
'include/pybind11/detail/typeid.h'
'include/pybind11/attr.h'
,
'include/pybind11/buffer_info.h'
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment