Swig: How to wrap double& (double passed by reference)?
Asked Answered
L

4

6

I am using SWIG to access C++ code from Python. How do I elegantly wrap a function that returns values in variables passed by reference like

void set(double&a) {
  a = 42.;
}

I could not find out how to do this. In the best case I'd be able to use the function in Python with Python floats:

>>> b = 2.
>>> set(b)
>>> print b
42.0

At the moment it gives me a TypeError: in method 'TestDouble_set', argument 2 of type 'double &'.

Lunseth answered 12/8, 2010 at 18:6 Comment(2)
It is possible to achieve this using the cpointer.i provided by SWIG, but it is than rather cumbersome.Lunseth
For an example, see: swig.org/Doc3.0/Python.html#Python_nn47Medicable
R
5

Do it this way:

Your swig interface file:

  %include <typemaps.i>

  %apply double& INOUT { double& a };
  void set(double& a);

Usage in python script:

  a = 0.0
  a = set(a)
  print a

If your function returns something (instead of being a void), do the below in python

  ret, a = set(a)

Checkout the documentation for typemaps in swig. You can do INPUT, OUTPUT & INOUT for arguments. HTH

Note that this solution relies on the SWIG-provided OUTPUT typemaps defined in typemaps.i library, which pre-defines the typemaps being used by the %apply command above.

typemaps.i defines input/output typemaps for C++ primitive types (see the above link to the SWIG documentation for more info); however, you have into include the typemaps.i library in your interface file for SWIG to use them. (Hence why some commenters likely found the original solution wasn't working for them.)

Radburn answered 17/12, 2010 at 19:33 Comment(3)
I get: >>> a = TestDouble.setx(a) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: in method 'setx', argument 1 of type 'double &'Lunseth
I have the above in an API & my fellow developers are using it day in & out. Is the above error generated by swig while generating the bindings? Are you including the header between %{ ... %}. Can you post a bigger chunk of your .i file? Start with a simple project with just one function setx() & then setx(double&) & then add the class.Radburn
I also get the same error at run-time even with this proposed fix here. SWIG version is 3.0.5.Medicable
S
1

Note that the accepted (correct) solution relies on the SWIG-provided OUTPUT typemaps defined in typemaps.i library, which pre-defines the typemaps being used by the %apply command above.

typemaps.i defines input/output typemaps for C++ primitive types (see the above link to the SWIG documentation for more info); however, you have to include the typemaps.i library in your interface file for SWIG to use them. (Hence why some commenters likely found the original solution wasn't working for them.)

Scenario answered 23/8, 2017 at 16:17 Comment(0)
R
0

hmm - are you using the latest version of SWIG? The documentation seems to indicate that this works -- from the manual:

C++ references are supported, but SWIG will treat them as pointers. For example, a declaration like this :

class Foo {
public:
    double bar(double &a);
}

will be accessed using a function like this :

double Foo_bar(Foo *obj, double *a) {
    obj->bar(*a);
}

Functions returning a reference will be mapped into functions returning pointers.

I don't know how you map that on the python side...does python have something like perl references?

Retrieve answered 12/8, 2010 at 19:10 Comment(1)
Not the very latest, but SWIG Version 1.3.29. But I don't expect that this has changed recently.Lunseth
D
0

It has been very helpful. I recently encountered similar issue, I found this on swig site: (the Return by value part)

I applied it to my interface file (c++ method returning double* -convert it to c#) it seems working.

Dayna answered 6/1, 2023 at 17:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.