On 5/21/2014 8:46 AM, Marvin Greenberg wrote:
Bob Hood wrote:
Bump.

On 5/8/2014 2:02 PM, Bob Hood wrote:
I'm using SWIG 2.0.4 with Python.

I've run into the first instance where I need to have an 'argout' mechanism
for a Director-controlled method.  Something along these lines:

     typedef double Vector[3];
     ...
     class MyClass
     {
        ...
        virtual int get_pos(Vector v);    //<-- 'v' is an output-onlyargument
     };

with

     %feature("director") MyClass;

in the interface file.

I've applied the "%typemap(directorargout) Vector" and achieved the desired
effect.  However, it appears that the generated Python method continues to
require the Vector 'v' argument to the method, even though it serves no useful
purposeand is not of a known type to Python; e.g. this works properly:

     def get_pos(self, v):
         return (1, (0, 0, 0))

However, if I attempt to leave off the 'v' argument:

     def get_pos(self):
         return (1, (0, 0, 0))

I get an error about the method requiring 1 argument with 2 provided.  Is
there a way that I can tell SWIG that the Python-based argument is irrelevant
(perhaps using some kind of %ignore directive) and that it should not attempt
to pass it to the Python code when invoking PyObject_CallMethod()?


I think you're misunderstanding something pretty basic about output arguments.  If you have a function or method like

   void foo(int& outarg);

Then the implementation is going to pass the argument value by doing something to the passed argument, not by returning extra values. Like,

  outarg = 1;

In your method you declare the C++ method as returning an integer, but then in your director implementation you proceed to pass out a tuple with an int and another tuple, not an int.  It "works" because python is not statically typed.  It certainly isn't doing what you think.  Your get_pos implementation would need to look something like

  def get_pos(self,v):
    v[0]=0
    v[1]=1
    v[2]=2
    return 0

I'm not that familiar with the details of the code generated for python directors, or how directorargout modifies it (makes it a 1 element array?) but its really besides the point.

Thanks for the response, Marvin.

There is a typemap defined (not included) that converts the (0, 0, 0) tuple back into a double[3] for return to the caller.

I don't believe I've misunderstood anything about output arguments (at least, in each individual language).  The issue here is the middleware code that SWIG generates.  The argument type of 'v' is opaque when it arrives in Python ("<type 'SwigPyObject'>") due to the "%typemap(directorargout) Vector" declaration, so your Python code above will not function because 'v' is not a known Python type -- an exception will be raised.

From the SWIG 2.x docs regarding "directorargout":
"directorargout typemaps allow your [target language] code to emulate this by specifying additional return values to be put into the output parameters. ... In this case, your return to the caller must be a list containing the normal function return first, followed by any argout values in order. These argout values will be taken from the list and assigned to the values to be returned to C++ through directorargout typemaps. In the event that you don't specify all of the necessary values, integral values will read zero, and struct or object returns have undefined results."
Unless I'm misunderstanding the above passage (which is taken from the "Ocaml" section, but I assume is valid for all target languages), the output argument value(s) have to be part of the return statement (as in my Python code), not assigned directly to the arguments provided to the Python function/method (which will fail due their opaque data types).  Assuming that's correct, the argument provided (in this case 'v') is completely useless because it is strictly designated as "output", and actually cannot be used as input anyway because it is not an accessible data type.

I suppose it's possible I'm missing a crucial point here.