how to use default arguments in c++? - python

in python I can write:
def test(a, b=None):
if b is None:
return
else:
print(123)
in cpp, it's better to avoid pointers, so I use reference instead,
so how to do the same thing?
#include "stdio.h"
void test(int a, const int &b) {
// how to check ?? since b should not be nullptr
printf("123\n"); };
int main() { test(); }

in cpp, it's better to avoid pointers, so I use reference instead
References can't refer to NULL, so pointers are the traditional way to do this, e.g. void test(int a, const int *b=NULL). Much of the reason references are encouraged over pointers is because it saves you from handling NULL arguments; if you need NULL arguments, references aren't saving you from anything.
std::optional is sometimes used for similar scenarios, but it's much newer (C++17), and I don't think there is strong consensus on whether it's preferable; that said, using it with std::nullopt as the default is close to what you've got already, and a reasonable way to handle the problem.
The alternative (mentioned in the answers to the above linked question) is just to overload the function twice, once with the argument, and once without; this could be combined with the std::optional approach to allow simpler calling for users only passing one argument (with a default, the generated code inlines the creation of the default argument at each call site that relies on it), but still implementing the function via common code (the single argument function just turning around and calling the two-argument function).

C++ references cannot be NULL.They always point to valid object,initialised during their declaration.

As mentioned in the other answers, NULL references aren't allowed in C++, so you can't use NULL as a default value for a by-reference argument, and std::optional would be a good choice instead.
You can define your own sentinel-object though, to perform the same function as NULL without actually being a NULL-reference, like this:
#include "stdio.h"
const int & get_sentinel_ref()
{
static int sentinel = 0; // must be declared static
return sentinel; // in order to have a fixed address
}
void test(int a, const int &b = get_sentinel_ref())
{
// Check if b is referring to our sentinel-value or not
// Note that I'm comparing memory-addresses here, not values
// otherwise the code would do the wrong thing if the user
// passed in zero (or whatever dummy-value sentinel is set
// to in the get_sentinel_ref() function above)
if (&b == &get_sentinel_ref())
{
printf("a is %i, but you didn't supply a second argument!\n", a);
}
else
{
printf("a is %i, b is %i\n", a, b);
}
}
int main(int, char **)
{
test(5);
test(6,7);
return 0;
}
... When run, the above program prints:
a is 5, but you didn't supply a second argument!
a is 6, b is 7

Related

pybind11 buffer protocol with class members

I'm trying to use pybind11 to bind a struct that looks like this
struct myStruct {
int na;
int nb;
double* a;
double* b;
}
I'm not sure the right way to go about it. The examples in the pybind11 documentation show how to attach buffer protocol semantics to an object, but not to a class member.
I don't have the luxury of changing the interface of myStruct to contain std::vectors either which would allow me to use the usual .def_readwrite().
I've tried doing something like this
py::class_<myStruct>(m, "myStruct")
.def_property("a",
[](myStruct &s) {return py::array<double>({s.na}, {sizeof(double), s.a};)},
[](myStruct &s, py::array_t<double> val) {std::copy((double*) val.request().ptr, (double*) val.request().ptr + s.na, s.a);)}
)
Which compiles, but in python I don't see changes persist in the underlying data
print(my_struct.a[0]) # prints 0.0
my_struct.a[0] = 123.0
print(my_struct.a[0]) # still prints 0.0
Hey most likely not the most elegant answer, but maybe it gives you a starting point and temporary solution. I think what you need to do is use shared pointers.
Under https://github.com/pybind/pybind11/issues/1150 someone asked something similar but I was not able to adapt it to your example and only got the same result to yours with no changes to the data.
What worked for me in your specific example was using the shared_ptr and defining setter and getter functions for the pointers with a simple def_property for the pybin11 class.
class class_DATA{
public:
int na;
std::shared_ptr<double> a;
void set_a(double a){*class_DATA::a = a; };
double get_a(void){return *class_DATA::a; };
};
PYBIND11_MODULE(TEST,m){
m.doc() = "pybind11 example plugin";
//the costum class
py::class_<class_DATA>(m, "class_DATA", py::dynamic_attr())
.def(py::init<>()) //needed to define constructor
.def_readwrite("na", &class_DATA::na)
.def_property("a", &class_DATA::get_a, &class_DATA::set_a, py::return_value_policy::copy);
}

boost-python when C++ method returns std::map<string,X*>

I'm exposing an API to Python, written in C++ that I have no access to change, using Boost Python.
I have successfully exposed methods returning references to a std:map where the key,value pairs are value types - eg:
class_< std::map<std::string, std::string> >("StringMap")
.def(map_indexing_suite< std::map<std::string, std::string>, true >());
This works seamlessly. But when trying to achieve a similar result where the map values are pointers to classes I've exposed within the API doesn't work:
struct X_wrap : X, wrapper<X>
{
X_wrap(int i): X(i) {}
// virtual methods here, omitted for brevity - as unlikely to be the issue
}
BOOST_PYTHON_MODULE(my_py_extension)
{
class_< std::map<std::string, X*> >("XPtrMap")
.def(map_indexing_suite< std::map<std::string, X*> >());
class_<X_wrap, boost::noncopyable, bases<XBase> >("X", init<int>())
// other definitions omitted
}
Error seen in g++ 7.3.0:
/usr/include/boost/python/detail/caller.hpp:100:98: error: ‘struct boost::python::detail::specify_a_return_value_policy_to_wrap_functions_returning<X*>’ has no member named ‘get_pytype’
I understand why the compiler is complaining - the X* in the map needs to be wrapped in a call policy so that it can be returned to Python, just like with a basic method that returns a raw pointer.
My question is what is the best way to do this?
From Googling it strikes that I can perhaps specify a DerivedPolicies child class of map_indexing_suite that will overload the necessary parts to wrap the X* in an appropriate return_value_policy. However so far I've be unsuccessful in putting anything together that the compiler doesn't bawk at!
I also suspect I can literally copy-and-paste the whole map_indexing_suite and rename it, and make the changes therein to produce a new indexing_suite with the right return_value_policy, but this seems ugly compared to the solution using DerviedPolicies - assuming I'm right that DeriviedPolicies can be used at all!
Any help, pointers, or examples gratefully received!
EDIT
I have proved that the cut-and-paste option works with a single trivial change of is_class to is_pointer. It's curious that is_pointer is not allowed in the original as the target policy can handle pointers. I'm yet to convince myself that it's an object lifetime restriction that means pointers are not allowed in the original?
The whole class is public so I suspect it's possible to avoid the full cut-and-paste by simply inheriting from map_indexing_suite or perhaps by using the mysterious DerivedPolicies parameter?
extension_def(Class& cl)
{
// Wrap the map's element (value_type)
std::string elem_name = "mapptr_indexing_suite_";
object class_name(cl.attr("__name__"));
extract<std::string> class_name_extractor(class_name);
elem_name += class_name_extractor();
elem_name += "_entry";
typedef typename mpl::if_<
mpl::and_<is_pointer<data_type>, mpl::bool_<!NoProxy> >
, return_internal_reference<>
, default_call_policies
>::type get_data_return_policy;
class_<value_type>(elem_name.c_str())
.def("__repr__", &DerivedPolicies::print_elem)
.def("data", &DerivedPolicies::get_data, get_data_return_policy())
.def("key", &DerivedPolicies::get_key)
;
}
EDIT 2
Now see answer
Slightly cleaner implementation from the cut-and-paste is to inherit map_indexing_suite - a few tweaks are needed to make this work.
This seems reasonably sensible - if someone chimes in with a neater solution or can better explain DerivedPolicies then great, otherwise I'll accept the below as the answer in a few days or so...
using namespace boost;
using namespace boost::python;
//Forward declaration
template <class Container, bool NoProxy, class DerivedPolicies>
class mapptr_indexing_suite;
template <class Container, bool NoProxy>
class final_mapptr_derived_policies
: public mapptr_indexing_suite<Container,
NoProxy, final_mapptr_derived_policies<Container, NoProxy> > {};
template <
class Container,
bool NoProxy = false,
class DerivedPolicies
= final_mapptr_derived_policies<Container, NoProxy> >
class mapptr_indexing_suite
: public map_indexing_suite<
Container,
NoProxy,
DerivedPolicies
>
{
public:
// Must be explicit if the compiler is
// going to take from the base class
using typename map_indexing_suite<
Container,NoProxy,DerivedPolicies>::data_type;
using typename map_indexing_suite<
Container,NoProxy,DerivedPolicies>::value_type;
// Only one class needs to be overridden from the base
template <class Class>
static void
extension_def(Class& cl)
{
// Wrap the map's element (value_type)
std::string elem_name = "mapptr_indexing_suite_";
object class_name(cl.attr("__name__"));
extract<std::string> class_name_extractor(class_name);
elem_name += class_name_extractor();
elem_name += "_entry";
// use of is_pointer here is the only
// difference to the base map_indexing_suite
typedef typename mpl::if_<
mpl::and_<std::is_pointer<data_type>, mpl::bool_<!NoProxy> >
, return_internal_reference<>
, default_call_policies
>::type get_data_return_policy;
class_<value_type>(elem_name.c_str())
.def("__repr__", &DerivedPolicies::print_elem)
.def("data", &DerivedPolicies::get_data, get_data_return_policy())
.def("key", &DerivedPolicies::get_key)
;
}
};

SWIG in typemap works, but argout does not

I have this file foobar.h
class Foobar {
public: void method(int arg[2]) {};
};
After compiling SWIG interface to Python, if I try to run this method from Python it says
TypeError: in method 'Foobar_method', argument 2 of type 'int [2]'
Certainly. So I write this SWIG typemap:
%typemap(in) int [2] {}
and when I compile this, Python runs this method without complaining. So I think, I understand how to write a typemap.
But, if I change the typemap to argout:
%typemap(argout) int [2] {}
Now, Python goes back to the previous error.
I just do this directly from the SWIG manual, this should work without that error, just like in typemap.
What am I doing wrong???
What's wrong?
In short it's not an either/or proposition with these typemaps.
The key bit of information you're missing is the way multiple typemaps cooperate to wrap a single function.
argout gets inserted in the generated wrapper after the call has happened. It's your opportunity to copy the (now modified) input back to Python in a sensible way.
That doesn't address the issue of how the argument gets created and passed in before the call however.
You can see this quite clearly by inspecting the code generated by this interface:
%module test
%{
#include "test.h"
%}
%typemap(in) int[2] {
// "In" typemap goes here
}
%typemap(argout) int[2] {
// "argout" goes here
}
%include "test.h"
Which, when test.h is your example produces:
// ... <snip>
arg1 = reinterpret_cast< Foobar * >(argp1);
{
// "In" typemap goes here
}
(arg1)->method(arg2);
resultobj = SWIG_Py_Void();
{
// "argout" goes here
}
return resultobj;
// ... <snip>
In those typemaps the goal of the "in" typemap is to make arg2 a sensible value before the call and the "argout" typemap should do something sensible with the values after the call (possibly by changing the return value if you want).
What should be in the typemaps?
Typically for a function like that you might want to have the input typemap populate a temporary array from some Python inputs.
To do that we're going to need to change the input typemap first, asking SWIG to create a temporary array for us:
It's important that we get SWIG to do this for us, using the notation of adding parenthesis after the type instead of adding it inside the body of the typemap so that the scope is correct for the variable. (If we didn't the temporary wouldn't be accessible from the "argout" typemap still and would be cleaned up before the call itself was made even).
%typemap(in) int[2] (int temp[2]) {
// If we defined the temporary here then it would be out of scope too early.
// "In" typemap goes here
}
The code generated by SWIG now includes that temporary array for us, so we want to use the Python C API to iterate over our input. That might look something like:
%typemap(in) int[2] (int temp[2]) {
// "In" typemap goes here:
for (Py_ssize_t i = 0; i < PyList_Size($input); ++i) {
assert(i < sizeof temp/sizeof *temp); // Do something smarter
temp[i] = PyInt_AsLong(PyList_GetItem($input, i)); // Handle errors
}
$1 = temp; // Use the temporary as our input
}
(We could have chosen to use Python iterator protocol instead if we preferred).
If we compile and run the interface now we have enough to pass in an input, but nothing comes back yet. Before we write the "argout" typemap there's one thing still to notice in the generated code. Our temporary array in the generated code actually looks like int temp2[2]. That's not a mistake, SWIG has by default renamed the variable to be derived from the argument position in order to permit the same typemap to be applied multiple times to a single function call, once per argument if needed.
In my "argout" typemap I'm going to return another Python list with the new values. This isn't the only sane choice by a long way though - there are other options if you prefer.
%typemap(argout) int[2] {
// "argout" goes here:
PyObject *list = PyList_New(2);
for (size_t i = 0; i < 2; ++i) {
PyList_SetItem(list, i, PyInt_FromLong(temp$argnum[i]));
}
$result = list;
}
The two points of note in this are firstly that we need to write temp$argnum explicitly to match the transformation that SWIG did on our temporary array and secondly that we're using $result as the output.
Purely output arguments
Often we have an argument that is just used for output, not input. For these it makes no sense to force the Python user to supply a list that's just going to be ignored.
We can do that by modifying the "in" typemap, using numinputs=0 to indicate that no input is expected from Python. You'll need to take care of initializing the temporary appropriately here too. The typemap now becomes simply:
%typemap(in,numinputs=0) int[2] (int temp[2]) {
// "In" typemap goes here:
memset(temp, 0, sizeof temp);
$1 = temp;
}
So now the "in" typemap doesn't actually take any input from Python at all. It can be seen as simply preparing the input to the native call.
By way of an aside you can avoid the name mangling that SWIG applies (with the cost of not being able to use the same typemap multiple times on the same function, or with another typemap that has a name clash) by using noblock=1 in the "in" typemap. I wouldn't recommend that though.
Non-fixed array length?
Finally it's worth noting that we can write all of these typemaps to be more generic and work for any, fixed, size array. To do that we change 2 to "ANY" in the typemap matching and then use $1_dim0 instead of 2 inside the typemap bodies, so the whole interface at the end of that becomes:
%module test
%{
#include "test.h"
%}
%typemap(in,numinputs=0) int[ANY] (int temp[$1_dim0]) {
// "In" typemap goes here:
memset(temp, 0, sizeof temp);
$1 = temp;
}
%typemap(argout) int[ANY] {
// "argout" goes here:
PyObject *list = PyList_New($1_dim0);
for (size_t i = 0; i < $1_dim0; ++i) {
PyList_SetItem(list, i, PyInt_FromLong(temp$argnum[i]));
}
$result = list;
}
%include "test.h"

How to create lambda's from Python/C

We're working on some Python/C-API code, and we've encountered a method that would like to be passed a callback. The method will ship periodic updates to the callback as a form a feedback. As it turns out, we're not that interested in periodic feedback. The only way to disable the method's default feedback mechanism is to pass it some kind of callback.
The technique we've employed is to declare a module level function that just returns None, ie:
static PyObject*
donothing(PyObject* self, PyObject* args) {
return Py_None;
}
But of course, this function also needs to be registered with the modules method table, ie:
static PyMethodDef methods[] = {
{"donothing", donothing, METH_VARARGS, "do nothing"},
...
{NULL}
};
Then, when we go to call the method, we need to grab a reference to this method, ie: PyObject_GetAttrString(module_reference, "donothing").
All of this feels like we're spending too much time spinning our wheels just to do nothing. Then it ocurred to me..hey, seems like a perfect use for lambda x: None. But after spending an hour with the Python/C-API docs, I can't figure out how one create's lambdas.
I see there are references to closures on the page http://docs.python.org/2/c-api/function.html, but I can't sort out the details on how one creates them.
Any pointers (or references to RTFM) would be greatly appreciated.
A lambda expressions is used to create simple anonymous functions. These have a PyFunction_Type wrapping an object of PyCode_Type, which is a chunk of executable code. But you're already on the C side, so creating a Python function would be a little too much. Instead you should create an object of PyCFunction_Type. This is similar to what you've tried to do with the module methods.
The boilerplate in C wouldn't be too big either, but only a few lines:
static PyObject *
donothing(PyObject *self, PyObject *args) {
Py_RETURN_NONE;
}
static PyMethodDef donothing_ml = {"donothing", donothing, METH_VARARGS, "doc"};
The object then is created with PyCFunction_New(&donothing_ml, NULL) which yields a <built-in function donothing>. This function is independent of your module and can be used like any other PyObject.
It's not exactly a high level lambda, but rather a low level implementation of lambda *args: None.
However if you'd really like to create a high level lambda you can do this with a single statement like dastrobu proposed
l = PyRun_String("lambda *args: None", Py_eval_input, PyEval_GetGlobals(), NULL);
or if you'd like to assemble it yourself you could do
PyCodeObject *c = (PyCodeObject *) Py_CompileString("None", "fn", Py_eval_input);
#if PY_MAJOR_VERSION >= 3
c->co_name = PyUnicode_FromString("<c-lambda>"); // function name
#else
c->co_name = PyString_FromString("<c-lambda>"); // function name
#endif
c->co_flags |= CO_VARARGS; // accept *args
c->co_nlocals = 1; // needed in Python 3
l = PyFunction_New((PyObject *) c, PyEval_GetGlobals());
In both cases you'll get a function with dissasembled code dis(l) equivalent to a lambda:
1 0 LOAD_CONST 0 (None)
3 RETURN_VALUE

In Python, how to use a C++ function which returns an allocated array of structs via a ** parameter?

I'd like to use some existing C++ code, NvTriStrip, in a Python tool.
SWIG easily handles the functions with simple parameters, but the main function, GenerateStrips, is much more complicated.
What do I need to put in the SWIG interface file to indicate that primGroups is really an output parameter and that it must be cleaned up with delete[]?
///////////////////////////////////////////////////////////////////////////
// GenerateStrips()
//
// in_indices: input index list, the indices you would use to render
// in_numIndices: number of entries in in_indices
// primGroups: array of optimized/stripified PrimitiveGroups
// numGroups: number of groups returned
//
// Be sure to call delete[] on the returned primGroups to avoid leaking mem
//
bool GenerateStrips( const unsigned short* in_indices,
const unsigned int in_numIndices,
PrimitiveGroup** primGroups,
unsigned short* numGroups,
bool validateEnabled = false );
FYI, here is the PrimitiveGroup declaration:
enum PrimType
{
PT_LIST,
PT_STRIP,
PT_FAN
};
struct PrimitiveGroup
{
PrimType type;
unsigned int numIndices;
unsigned short* indices;
PrimitiveGroup() : type(PT_STRIP), numIndices(0), indices(NULL) {}
~PrimitiveGroup()
{
if(indices)
delete[] indices;
indices = NULL;
}
};
Have you looked at the documentation of SWIG regarding their "cpointer.i" and "carray.i" libraries? They're found here. That's how you have to manipulate things unless you want to create your own utility libraries to accompany the wrapped code. Here's the link to the Python handling of pointers with SWIG.
Onto your question on getting it to recognize input versus output. They've got another section in the documentation here, that describes exactly that. You lable things OUTPUT in the *.i file. So in your case you'd write:
%inline{
extern bool GenerateStrips( const unsigned short* in_dices,
const unsigned short* in_numIndices,
PrimitiveGroup** OUTPUT,
unsigned short* numGroups,
bool validated );
%}
which gives you a function that returns both the bool and the PrimitiveGroup* array as a tuple.
Does that help?
It's actually so easy to make python bindings for things directly that I don't know why people bother with confusing wrapper stuff like SWIG.
Just use Py_BuildValue once per element of the outer array, producing one tuple per row. Store those tuples in a C array. Then Call PyList_New and PyList_SetSlice to generate a list of tuples, and return the list pointer from your C function.
I don't know how to do it with SWIG, but you might want to consider moving to a more modern binding system like Pyrex or Cython.
For example, Pyrex gives you access to C++ delete for cases like this. Here's an excerpt from the documentation:
Disposal
The del statement can be applied to a pointer to a C++ struct
to deallocate it. This is equivalent to delete in C++.
cdef Shrubbery *big_sh
big_sh = new Shrubbery(42.0)
display_in_garden_show(big_sh)
del big_sh
http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/version/Doc/Manual/using_with_c++.html

Categories

Resources