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

Oded Padon opadon at yahoo.com
Mon Aug 2 22:46:37 CEST 2010


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 <nat at lindenlab.com> wrote:

> From: Nat Goodspeed <nat at lindenlab.com>
> Subject: Re: [C++-sig] Calling a C++ function with arguments by reference (lvalues)
> To: "Development of Python/C++ integration" <cplusplus-sig at python.org>
> 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).
> 
> <boring anecdote>
> 
> 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.
> 
> </boring anecdote>
> 
> 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 at python.org
> http://mail.python.org/mailman/listinfo/cplusplus-sig
> 


      



More information about the Cplusplus-sig mailing list