[C++-sig] division operator in 3.1

2010-08-02 Thread Trigve Siver
Hi,
I've found bug in boost python with division operator. Division operator  with 
custom types doesn't work with python 3.1. It is because there were  some 
changes 

in this regard in python 3. I've created ticket with patch 
https://svn.boost.org/trac/boost/ticket/4497 . Can somebody look at  it?
 
Thanks

Trigve


  
___
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig


[C++-sig] Calling a C++ function with arguments by reference (lvalues)

2010-08-02 Thread Oded Padon
Hello everybody,

I'm very new to Boost.Python, and I just spent hours trying to do something 
trivial, and couldn't get it. The C++ code is:

void add(int const a, int const b, int const& c)
{
c = a + b;
}

BOOST_PYTHON_MODULE(hello_ext)
{
using namespace boost::python;
def("add", add);
}

When I tried to call this function from python I got the following error:
>>> import hello_ext
>>> x = int()
>>> y = int()
>>> z = int()
>>> hello_ext.add(x,y,z)
Traceback (most recent call last):
  File "", line 1, in 
Boost.Python.ArgumentError: Python argument types in
hello_ext.add(int, int, int)
did not match C++ signature:
add(int, int, int {lvalue})

How can I get this to work?
I must emphasize that I wish to have functions that get arguments by reference 
and change them. Returning the values using the return mechanism isn't what I 
want to do (I have functions that get and set many many arguments, and I hardly 
wish to rewrite them).

Thanks,
Oded


  

___
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] Calling a C++ function with arguments by reference (lvalues)

2010-08-02 Thread Nat Goodspeed

Oded Padon wrote:


The C++ code is:

void add(int const a, int const b, int const& c)
{
c = a + b;
}


This doesn't even compile under g++ 4.0.1 (Mac):
error: assignment of read-only reference 'c'

I hope you're not using a compiler that accepts such code as legal?


I must emphasize that I wish to have functions that get arguments

> by reference and change them. Returning the values using the return
> mechanism isn't what I want to do (I have functions that get and set
> many many arguments, and I hardly wish to rewrite them).



Many moons ago I had the dubious pleasure of using a FORTRAN compiler 
that was old and dumb even for the time. With this compiler, all 
parameters were passed by non-const reference. One of my team was 
delegated to write a subroutine that accepted certain parameters. There 
was miscommunication about the expected parameter order, and the calling 
code ended up passing the integer literal '5' in the parameter slot to 
which the subroutine stored its result.


From that point on, everywhere the literal '5' appeared in the source, 
the executable was instead referencing the result of some computation.


Merriment ensued as the program confounded all attempts to predict its 
behavior.


You are proposing to do the same to the Python interpreter. It's 
appropriate for Boost.Python to try to make that difficult.




Suppose you were writing this code from scratch in pure Python. How 
would you approach the problem? This won't work:


def add(a, b, c):
c = a + b

def caller():
c = 0
add(1, 2, c)
assert c == 3   # FAIL

One way would be to keep some set of working variables in an object, and 
pass that object into the function that wants to modify them:


class Vars(object):
def __init__(self):
self.a = 0
self.b = 0
self.c = 0

def add(a, b, vars):
vars.c = a + b

def caller():
v = Vars()
add(1, 2, v)
assert v.c == 3

Or you could keep working values in a dict, if you prefer dict lookup to 
attribute references.


You can code your C++ add() function to accept its 'vars' parameter as a 
boost::python::object. If you pass a class object, you can reference 
vars.attr("c"). If you pass a dict, you can reference vars["c"].


See also: 
http://www.boost.org/doc/libs/1_43_0/libs/python/doc/tutorial/doc/html/python/embedding.html#python.using_the_interpreter 


___
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] Calling a C++ function with arguments by reference (lvalues)

2010-08-02 Thread Oded Padon
Thank you for your rapid response.
I had a typo in my code. It should have been:
void add(int const a, int const b, int & c)
{
c = a + b;
}
i.e. the last argument is passed by non-const reference.

One solution is indeed to rewrite the function to accept either a
python object (class, dict, etc.) or a C++ defined struct by reference, but 
this means a change to the function's coding style, which I'd like to preserve.
I somehow feel that there should be a way to achieve this, as the python module 
does compile, and boost.python does understand the signature of the function 
that gives my desired behavior:
"
did not match C++ signature:
add(int, int, int {lvalue})
"
This makes me think that boost.python does know how to handle functions of such 
signature, but I do not yet know how to invoke them from python.

There is another reason why I think this has to be possible. It is possible 
using ctypes. Using ctypes with the same C++ code written above (except for 
extern "C"), the following python code:

import ctypes;
lib_cpp = ctypes.CDLL('./test_cpp.so')
result = ctypes.c_int(0);
lib_cpp.add(1, 2, ctypes.byref(result));
print result;

prints: "c_long(3)"

I do prefer however to use boost.python, as I would at a later stage want to 
expose C++ classes to python, but exposing functions like the above is step one 
for me.

Thanks again,
Oded

--- On Mon, 8/2/10, Nat Goodspeed  wrote:

> From: Nat Goodspeed 
> Subject: Re: [C++-sig] Calling a C++ function with arguments by reference 
> (lvalues)
> To: "Development of Python/C++ integration" 
> Date: Monday, August 2, 2010, 6:24 PM
> Oded Padon wrote:
> 
> > The C++ code is:
> > 
> > void add(int const a, int const b, int const& c)
> > {
> >     c = a + b;
> > }
> 
> This doesn't even compile under g++ 4.0.1 (Mac):
> error: assignment of read-only reference 'c'
> 
> I hope you're not using a compiler that accepts such code
> as legal?
> 
> > I must emphasize that I wish to have functions that
> get arguments
> > by reference and change them. Returning the values
> using the return
> > mechanism isn't what I want to do (I have functions
> that get and set
> > many many arguments, and I hardly wish to rewrite
> them).
> 
> 
> 
> Many moons ago I had the dubious pleasure of using a
> FORTRAN compiler that was old and dumb even for the time.
> With this compiler, all parameters were passed by non-const
> reference. One of my team was delegated to write a
> subroutine that accepted certain parameters. There was
> miscommunication about the expected parameter order, and the
> calling code ended up passing the integer literal '5' in the
> parameter slot to which the subroutine stored its result.
> 
> From that point on, everywhere the literal '5' appeared in
> the source, the executable was instead referencing the
> result of some computation.
> 
> Merriment ensued as the program confounded all attempts to
> predict its behavior.
> 
> You are proposing to do the same to the Python interpreter.
> It's appropriate for Boost.Python to try to make that
> difficult.
> 
> 
> 
> Suppose you were writing this code from scratch in pure
> Python. How would you approach the problem? This won't
> work:
> 
> def add(a, b, c):
>     c = a + b
> 
> def caller():
>     c = 0
>     add(1, 2, c)
>     assert c == 3   # FAIL
> 
> One way would be to keep some set of working variables in
> an object, and pass that object into the function that wants
> to modify them:
> 
> class Vars(object):
>     def __init__(self):
>         self.a = 0
>         self.b = 0
>         self.c = 0
> 
> def add(a, b, vars):
>     vars.c = a + b
> 
> def caller():
>     v = Vars()
>     add(1, 2, v)
>     assert v.c == 3
> 
> Or you could keep working values in a dict, if you prefer
> dict lookup to attribute references.
> 
> You can code your C++ add() function to accept its 'vars'
> parameter as a boost::python::object. If you pass a class
> object, you can reference vars.attr("c"). If you pass a
> dict, you can reference vars["c"].
> 
> See also: 
> http://www.boost.org/doc/libs/1_43_0/libs/python/doc/tutorial/doc/html/python/embedding.html#python.using_the_interpreter
> 
> ___
> Cplusplus-sig mailing list
> Cplusplus-sig@python.org
> http://mail.python.org/mailman/listinfo/cplusplus-sig
> 


  

___
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] Calling a C++ function with arguments by reference (lvalues)

2010-08-02 Thread Jim Bosch

On 08/02/2010 01:46 PM, Oded Padon wrote:

import ctypes;
lib_cpp = ctypes.CDLL('./test_cpp.so')
result = ctypes.c_int(0);
lib_cpp.add(1, 2, ctypes.byref(result));
print result;

prints: "c_long(3)"

I do prefer however to use boost.python, as I would at a later stage want to 
expose C++ classes to python, but exposing functions like the above is step one 
for me.



This works because ctypes provides integer types ("c_int", etc.) which 
are mutable in Python; in other words, you can change the value of a 
ctypes.c_int object.


That isn't true for regular Python int objects (or str objects, or tuple 
objects, for instance).  Whenever it *looks* like you've changed one, as in:


a = 3
a += 2

... you actually haven't.  The second line won't add 2 to the integer 
object that previously had the value 3.  It might construct a new int 
object with a value of 5.  And in some Python implementations, it might 
just increment the reference count of a pre-existing global integer 
object that already has the value 5 and set "a" to be a reference to 
that object.  The point is that immutable types in Python simply cannot 
be modified in place, and Python plays tricks to make it *seem* like 
they're being modified while it ensures that they never really are.


If you really want to go down this route, you can create a C++ object 
that behaves like an int and wrap it with Boost.Python; that object 
won't be immutable, and you can give it the necessary operators to 
interact properly with regular ints.  And you'll be able to pass it 
by-value to functions.  But my guess is that it's probably much easier 
just to pass a dictionary to all of your functions.


Hope that helps!

Jim Bosch
___
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] Calling a C++ function with arguments by reference (lvalues)

2010-08-02 Thread Nat Goodspeed

Oded Padon wrote:


There is another reason why I think this has to be possible.

> It is possible using ctypes. Using ctypes with the same C++
> code written above (except for extern "C"), the following python code:


import ctypes;
lib_cpp = ctypes.CDLL('./test_cpp.so')
result = ctypes.c_int(0);
lib_cpp.add(1, 2, ctypes.byref(result));
print result;

prints: "c_long(3)"


Yes. In this case, you allocated and passed a specific ctypes object 
guaranteed to be compatible with a C++ int.


I still stand by my earlier point. Python doesn't recognize the concept 
of 'const'. All int values are equally immutable. If Boost.Python were 
to allow usage like this:


result = int()
cppmodule.add(1, 2, result)
assert result == 3

then what should happen in this innocent-looking case?

result = int()
cppmodule.add(result, 1, 2)

Or consider this. In recent versions of the Python interpreter, if you 
assign (say) 5 to a variable and then double it enough times, you will 
eventually produce a value larger than a C++ int. Unlike C++, Python 
will grow the storage associated with that variable to be able to 
represent the value exactly.


What should happen when you try to pass *that* value to a C++ int& 
parameter?


If you're happy with the ctypes approach, you could easily introduce a 
convention like this:


class RefInt(object):
def __init__(self, value=int()):
self.value = value

def __int__(self):
return self.value

# ...other operations as desired for convenience...

Now, assuming you've coded your C++ add() function to accept a RefInt, 
you can write:


result = RefInt(0)
cppmodule.add(1, 2, result)
assert int(result) == 3

which is just as facile as the ctypes code you cited.
___
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig