exposing method with unsigned char & argument using Boost.Python - c++

I've closed-source C++ library, which provides header files with code equivalent to:
class CSomething
{
public:
void getParams( unsigned char & u8OutParamOne,
unsigned char & u8OutParamTwo ) const;
private:
unsigned char u8OutParamOne_,
unsigned char u8OutParamTwo_,
};
I'm trying to expose that to Python, my wrapper code is something like this:
BOOST_PYTHON_MODULE(MySomething)
{
class_<CSomething>("CSomething", init<>())
.def("getParams", &CSomething::getParams,(args("one", "two")))
}
Now I'm trying to use that in Python, which fails horribly:
one, two = 0, 0
CSomething.getParams(one, two)
Which results in:
ArgumentError: Python argument types in
CSomething.getParams(CSomething, int, int)
did not match C++ signature:
getParams(CSomething {lvalue}, unsigned char {lvalue} one, unsigned char {lvalue} two)
What do I need to change either in the Boost.Python wrapper code or Python code to make it work? How do I add some Boost.Python magic to automatically cast PyInt to unsigned char and vice-versa?

Boost.Python is complaining about a missing lvalue parameter, a concept which does not exist in Python:
def f(x):
x = 1
y = 2
f(y)
print(y) # Prints 2
The x paramter of the f function is not a C++-like reference. In C++ the output is different:
void f(int &x) {
x = 1;
}
void main() {
int y = 2;
f(y);
cout << y << endl; // Prints 1.
}
You have a few choices here:
a) Wrap the CSomething.getParams function to return a tuple of the new parameters values:
one, two = 0, 0
one, two = CSomething.getParams(one, two)
print(one, two)
b) Wrap the CSomething.getParams function to accept a class instance as parameter:
class GPParameter:
def __init__(self, one, two):
self.one = one
self.two = two
p = GPParameter(0, 0)
CSomething.getParams(p)
print(p.one, p.two)

Related

a pointer to function within a operator

for homework, I need to write a program in cpp with a class composed of an array of pointer to function and operators. I need to create an operator + so as when in the main, this would happen:
int main()
{
int SIZE = 5;
ptrF* arrPtrF = new ptrF[SIZE];
arrPtrF[0] = add;
arrPtrF[1] = sub;
arrPtrF[2] = mult;
arrPtrF[3] = div1;
arrPtrF[4] = pow;
Delegate D1(arrPtrF, SIZE)
cout<< D1[0](6, 7) + D1[0](1, 2)<<endl;
}
the outcome is 15
I am finding difficulty with writing the operator+ ( which in this case need to take take a object parameter)
at first i tried this:
Delegate Delegate:: operator + (const Delegate& b)
{
Delegate tmp;
tmp.m_ptrF[i] = m_ptrF[i] + b.m_ptrF[i];
return tmp;
}
but it gave me an error about the i and b.m_ptrF->initialized i and something about an enum type.
then i tried this:
int Delegate:: operator + (const Delegate& b)
{
int tmp;
int i, x,y;
tmp = m_ptrF[i](x, y) + b.m_ptrF[i](x, y);
return tmp;
}
but it gives me an error->initialized x,y,i knowing that i is index and x,y the parameters of the pointer to function.
what can i do to make it work?
It looks like D1[0](6, 7) is supposed to perform 6 + 7 returning an int and D1[0](1, 2) is supposed to perform 1 + 2 also returning an int. So the addition in D1[0](6, 7) + D1[0](1, 2) is just a regular int addition.
So in other words you are not supposed to be overloading Delegate::operator+ instead you are supposed to writing something like this
XXX Delegate::operator[](int i) const
{
...
}
where XXX is a function like type that will perform the addition on the later parameters.
So XXX will be something like
class XXX
{
public:
int operator()(int x, int y) const
{
...
}
...
};
But XXX will have to perform addition, or substraction or whatever, as appropriate.
So the expression D1[0](6, 7) becomes temp(6,7) where temp is an object of the XXX type above.
At least that's my best interpretation. It's clear that you have misunderstood your requirements.

overload [] operator to return a variant type

EDIT: thanks to the answers I was able to solve all the issues with my code. I post here the solution: it might be useful to somebody in the future. In particular, the suggestion of using a proxy class proved very useful! The example doens't consider all the cases but it should be trivial to add another type to the variant!
I am writing a C++ (C11 - Linux) custom class that sort of behaves like an unordered map {key, value}. I would like to overload the [] operator so that I can use the class with the same syntax as an unordered map: object[key] would return value.
The problem is that I need object[key] to return a variant type. I can store internally value as a string or struct but, when I retrieve it by using object[key], I need the returned value to be an int, float or string depending on some internal condition determined at runtime.
This is why I was thinking about using the boost::variant library ... but I am opened to any other suggestion. The only restriction is that the test class (in the example) have to compiled as a shared library .so and that the code must be C11 compatible (I mean compilable by GNU g++ 4.8.5).
I wrote a simple example to show what kind of behavior I would like The example is not meant to mean anything. It is just to illustrate the kind of error that I am getting. The real class that I am writing has a different structure but the usage of bool::variant and operator [] overload is the same.
test.cpp
#include <boost/variant.hpp>
typedef boost::variant<int, float> test_t;
class Test
{
int i ;
float f;
void set(int randomint, test_t tmp){
if ( randomint == 0 ) i = boost::get<int>(tmp);
else f = boost::get<float>(tmp);
}
test_t get(int randomint){
if ( randomint == 0 ) return i;
else return f;
}
struct IntOrFloat {
int randomint;
Test *proxy;
explicit operator int () const
{ return boost::get<int>(proxy->get(randomint)); }
void operator= (int tmp)
{ proxy->set(randomint, tmp); }
explicit operator float () const
{ return boost::get<float>(proxy->get(randomint)); }
void operator= (float tmp)
{ proxy->set(randomint, tmp); }
};
public:
IntOrFloat operator [](int randomint)
{ return IntOrFloat{randomint, this}; }
const IntOrFloat operator [](int randomint) const
{ return IntOrFloat{randomint, (Test *) this}; }
};
main.cpp
#include <iostream>
#include <boost/variant.hpp>
#include "test.cpp"
#define INTEGER 0
#define FLOAT 1
int main (void) {
Test test;
int i = 3;
float f = 3.14;
test[INTEGER] = i;
test[FLOAT] = f;
int x = (int) test[INTEGER];
float y = (float) test[FLOAT];
std::cout << x << std::endl;
std::cout << y << std::endl;
return 0;
}
To compile and run
g++ -fPIC -std=c++11 -shared -rdynamic -o test.so test.cpp
g++ -std=c++11 -o test main.cpp -Lpath/to/the/test.so -l:test.so
LD_LIBRARY_PATH="path/to/the/test.so" ./test
In C++, overload resolution does not happen on the return type, so given
int foo() { return 0; }
float foo() { return 0.f; }
there is no sanctioned way for the compiler to differentiate
int x = foo();
float f = foo();
. There is a trick using conversion operator overloads:
#include <iostream>
struct IntOrFloat {
operator int () const {
std::cout << "returning int\n";
return 0;
}
operator float () const {
std::cout << "returning float\n";
return 0.f;
}
};
IntOrFloat foo() { return IntOrFloat(); }
int main () {
int x = foo();
float f = foo();
}
You can force more verbosity by making the conversion explicit:
explicit operator int () const ...
explicit operator float () const ...
int x = static_cast<int>(foo());
int x = float(foo()); // old-style-cast
This proxy (or other conversion operator tricks) are as far as you'll to simulate return type overload resolution.
The idea once arised while searching a solution to supporting <euclidian vector> * <euclidian vector>-syntax, i.e. an operator* which either means dot product or vector product, depending on the type of the variable the product is assigned to.
In the end, it was not really practical and did not contribute positively to readability. The more verbose forms dot(vec, vec) and cross(vec, vec) were superior for several reasons, among which:
principle of least surprise: the computer graphics community is used to the terms "dot" and "cross"
less cryptic error messages: because this proxy technique is not idiomatic in C++, people are not used to the kind of error messages this temporal indirection yields
temporal and/or spatial locality: you are essentially returning a closure with code in it, which can be executed many times at many places. this can be doubly bad as it does not (actually, does) work well with auto & kind of declarations:
int main () {
const auto &f = foo();
const int g = f;
const int h = f;
std::cout << (int)f << "\n";
}
This prints something multiple times, going hand in hand with the least surprise principle. Of course this becomes less severe if your proxy basically just forwards readily available values. But the error messages won't become any better!
Note you can also incorporate template conversion operator overloads and wild metaprogramming. While worth a fun experiment, this is not something I'd love to put into a production code base, for maintenance and readability will even decrease.
What remains? Infinite possibilities; but some of the most feasible:
Variant datatypes
Tuple datatypes (look into std::tuple, which comes with conversion operators in case of distinct member types)
Different idioms (e.g. named methods instead of operator method)
Different algorithms
Different data structures
Different design patterns
When you use return i, what's happening underneath the hood is the creation of a temporary of type test_t that encapsulates that int value. This works fine in the function test::test_variant because the return type is test_t. This cannot work in the function test::operator[] because the return type is test_t&. The language prohibits creating a modifiable (l-value) reference to a temporary.
One way to make this work is to add a data member of type test_t to your class, with your test function operator[] setting this member and returning it rather than returning a temporary. Your real class will most likely do something different.

Callback functions with different arguments

I have two functions with a little different functionality, so I can't make them as template functions.
int func64(__int64 a) {
return (int) a/2;
}
int func32(int a) {
return a--;
}
Depending on variable b64, I would like to call func64 or func32. I don't want check if b64 is true many times in my code, so I use pointers to functions.
void do_func(bool b64) {
typedef int (*pfunc32)(int);
typedef int (*pfunc64)(__int64);
pfunc32 call_func;
if (b64)
call_func = func64; //error C2440: '=' : cannot convert from 'int (__cdecl *)(__int64)' to 'pfunc32'
else
call_func = func32;
//...
call_func(6);
}
How can I avoid this error and cast call_func to pfunc32 or pfunc64?
The language requires all functions called through the same function pointer to have the same prototype.
Depending on what you want to achieve, you could use the pointer/cast aproach already mentioned (which satisfies this requirement at the loss of type safety) or pass a union instead:
union u32_64
{
__int64 i64;
int i32;
};
int func64(union u32_64 a) {
return (int) a.i64/2;
}
int func32(union u32_64 a) {
return --a.i32;
}
void do_func(bool b64) {
typedef int (*pfunc)(union u32_64);
pfunc call_func;
if (b64)
call_func = func64;
else
call_func = func32;
//...
union u32_64 u = { .i64 = 6 };
call_func(u);
}
Pass a void pointer and cast it in the function body.
Of course this means less compiler control if you use the wrong type; if you call func64 and pass an int to it the program will compile and produce wrong results without giving you any tip of what is going wrong.
int func64(void *a) {
__int64 b = *((__int64*) a);
return (int) b/2;
}
int func32(void *a) {
int b = *((int *) a)
return b-1;
}
I need to call func32() or func64() depending on flag b64
So do that:
void do_func(bool b64) {
if (b64)
func64(6);
else
func32(6);
}
Well, first of all, please note that function func32 is returning the input argument as is.
This is because with return a--, you are returning the value of a before decrementing it.
Perhaps you meant to return a-1 instead?
In any case, you can simply declare this function as int func32(__int64 a).
This way, it will have the same prototype as function func64, but will work exactly as before.
BTW, calling a function through a pointer might be more "expensive" than a simple branch operation, so depending on your application, you might be better off with a simple if/else conditional statement...
Make a wrapper for func64:
int func64_as_32(int a) {
return func64(a);
}
Now you can assign either func32 or func64_as_32 to call_func since they have the same signature. The value you pass in, 6, has type int so passing it to func64_as_32 has the same effect as passing it directly to func64.
If you have call sites where you pass in a value of type __int64 then you'd do it the other way around, wrap func32.
As bool in C++ converts to int ( true => 1, false => 0 ) you can use b64 as array index. So take SJuan76's advice, convert your functions prototype to int f(void*) and put them into array int (*array_fun[2])(void* x); . You can call these functions then like that :
int p = 6;
array_fun[b64](&p);

How do I return a reference to a dynamic type from C++ and hold it in Python?

I'm writing some code that returns a column value from a row based on the column index. The row is updated from time to time in C++, and I'd like the python code to keep a reference to the column value. The following code reflects my current solution, in which I have to repeatedly fetch the column value.
struct Foo
{
PyObject * get(int pos)
{
// Position 0 is an integer value. Position 1 is a float value
if (pos == 0)
return Py_BuildValue ("i", m_int);
else
return Py_BuildValue ("f", m_float);
}
void set_int(int i)
{
m_int = i;
}
void set_float(float f)
{
m_float = f;
}
int m_int;
float m_float;
};
My bindings are simple:
class_<Foo> ("Foo")
.def("get", &Foo::get)
.def("set_int", &Foo::set_int)
.def("set_float", &Foo::set_float)
;
This works at the python level like this:
In [16]: foo = Foo()
In [17]: foo.set_int(1)
In [18]: foo.set_float(2.5)
In [19]: i = foo.get(0)
In [20]: f = foo.get(1)
In [21]: i
Out[21]: 1
In [22]: type(i)
Out[22]: int
In [23]: f
Out[23]: 2.5
In [24]: type(f)
Out[24]: float
So far, so good. However, when I modify foo, I'd like i and f to reflect the new values. Currently, they reflect the old values.
In [25]: foo.set_int(42)
In [26]: i
Out[26]: 1
How do I setup the C++ and binding code so that 'get' returns a reference to rather than a copy of the Foo member variables?
You need to wrap the integer values in an object class. Primitives are immutable in Python so when you return an int value it will never reference the original int, just a const copy. You could return a new struct of the form:
struct IntWrap {
int *value;
int get() { return *value; }
void set_int(int nval) { *value = nval; }
...
};
class_<IntWrap > ("IntWrap")
.def("get", &IntWrap::get)
.set("set_int", &IntWrap::set_int)
...
and make wrapper function bindings that treat the struct as a mutable integer in Python. This however, does violate the constness idiom of primitives in Python.
Here's a post on effectively inheriting from str or int, where you could make changes to the integer style object to use IntWrap instead (in case you want something that acts more like an int out of the box).

Boost.Fusion Functional: Calling functions with default arguments

Is it possible to use boost::fusion::invoke function to call a function that has default arguments without specifying those?
Example:
void foo(int x, int y = 1, int z = 2)
{
std::cout << "The sum is: " << (x + y + z) << std::endl;
}
...
// This should call foo(0). It doesn't work because the type of foo is void (*) (int, int, int).
boost::fusion::invoke(foo, boost::fusion::vector<int>(0));
// Works
boost::fusion::invoke(foo, boost::fusion::vector<int, int, int>(0, 1, 2));
I am writing a wrapper for bindings to a scripting language and default arguments would greatly improve the intuitive feel for the users of the wrapper. I am afraid though that the standard has not covered this case.
A side note:
I know one could work around it using functors:
struct foo {
void operator() (int x, int y = 1, int z = 2) { /* ... */ }
};
// Works because the functor adds an indirection
boost::fusion::invoke(foo(), boost::fusion::vector<int>(0));
This is however not an option as I don't want to force the users to create functors just to specify default arguments.
You can use bind (more info):
boost::fusion::invoke(boost::bind(foo, _1, 1, 2), boost::fusion::vector<int>(0));