This is a collection of a few more features listed that do not have a proper place yet in the rest of the documentation.
The C++ code used for the examples below can be found
here
, and it is assumed that that code is loaded at the start of any session. Download it, save it under the name
features.h
, and load it:
>>> import cppyy >>> cppyy.include('features.h') >>>
There are several conventional “special variables” that control behavior of functions or provide (internal) information. Often, these can be set/used in pythonizations to handle memory management or Global Interpreter Lock (GIL) release.
__python_owns__
: a flag that every bound instance carries and determines whether Python or C++ owns the C++ instance (and associated memory). If Python owns the instance, it will be destructed when the last Python reference to the proxy disappears. You can check/change the ownership with the __python_owns__ flag that every bound instance carries. Example:
>>> from cppyy.gbl import Concrete >>> c = Concrete() >>> c.__python_owns__ # True: object created in Python True >>>
__creates__
: a flag that every C++ overload carries and determines whether the return value is owned by C++ or Python: if
True
, Python owns the return value, otherwise C++.
__set_lifeline__
: a flag that every C++ overload carries and determines whether the return value should place a back-reference on
self
, to prevent the latter from going out of scope before the return value does. The default is
False
, but will be automatically set at run-time if a return value’s address is a C++ object pointing into the memory of
this
,或者若
self
is a by-value return.
__release_gil__
: a flag that every C++ overload carries and determines whether the Global Interpreter Lock (GIL) should be released during the C++ call to allow multi-threading. The default is
False
.
__useffi__
: a flag that every C++ overload carries and determines whether generated wrappers or direct foreign functions should be used. This is for PyPy only; the flag has no effect on CPython.
__sig2exc__
: a flag that every C++ overload carries and determines whether C++ signals (such as SIGABRT) should be converted into Python exceptions.
__cppname__
: a string that every C++ bound class carries and contains the actual C++ name (as opposed to
__name__
which has the Python name). This can be useful for template instantiations, documentation, etc.
It is usually easier to use a Python equivalent or code up the effect of an STL algorithm directly, but when operating on a large container, calling an STL algorithm may offer better performance. It is important to note that all STL algorithms are templates and need the correct types to be properly instantiated. STL containers offer typedefs to obtain those exact types and these should be used rather than relying on the usual implicit conversions of Python types to C++ ones. For example, as there is no
char
type in Python, the
std::remove
call below can not be instantiated using a Python string, but the
std::string::value_type
must be used instead:
>>> cppstr = cppyy.gbl.std.string >>> n = cppstr('this is a C++ string') >>> print(n) this is a C++ string >>> n.erase(cppyy.gbl.std.remove(n.begin(), n.end(), cppstr.value_type(' '))) <cppyy.gbl.__wrap_iter<char*> object at 0x7fba35d1af50> >>> print(n) thisisaC++stringing >>>
Typing
cppyy.gbl
all the time gets old rather quickly, but the dynamic nature of
cppyy
makes something like
from cppyy.gbl import *
impossible. For example, classes can be defined dynamically after that statement and then they would be missed by the import. In scripts, it is easy enough to rebind names to achieve a good amount of reduction in typing (and a modest performance improvement to boot, because of fewer dictionary lookups), e.g.:
import cppyy std = cppyy.gbl.std v = std.vector[int](range(10))
But even such rebinding becomes annoying for (brief) interactive sessions.
For CPython only (and not with tools such as IPython or in IDEs that replace the interactive prompt), there is a fix, using
from cppyy.interactive import *
. This makes lookups in the global dictionary of the current frame also consider everything under
cppyy.gbl
. This feature comes with a performance
penalty
and is not meant for production code. Example usage:
>>> from cppyy.interactive import * >>> v = std.vector[int](range(10)) >>> print(list(v)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> >>> cppdef("struct SomeStruct {};") True >>> s = SomeStruct() # <- dynamically made available >>> s <cppyy.gbl.SomeStruct object at 0x7fa9b8624320> >>>
For PyPy, IPython, etc.
cppyy.gbl
is simply rebound as
g
and
cppyy.gbl.std
is made available as
std
. Not as convenient as full lookup, and missing any other namespaces that may be available, but still saves some typing in may cases.
dir()
on a namespace shows the classes and functions
available for binding, even if these may not have been created yet.
Once created, namespaces are registered as modules, to allow importing from
them.
The global namespace is
cppyy.gbl
.
cppyy.nullptr
.
Starting C++11, the keyword
nullptr
is used to represent
NULL
.
For clarity of intent, it is recommended to use this instead of
None
(or the integer
0
, which can serve in some cases), as
None
is better
understood as
void
in C++.