1

I have the following C function which I'm trying to SWIG-ify:

void    GetAttOrder(int node, DCE_ORDER order, float att[3]);

which I want to call in Python and access via:

node = 0; order = DCD_TYPR;
attitude = GetAttOrder(node, order);
attitude[0] // 45.232

Where I've previously implemented the DCE_ORDER type as

typedef enum
{
  DCD_TPYR = 0,
  DCD_TYPR,
  DCD_TYRP,
  ...
  DCD_PRYT
} DCE_ORDER;

I've found some documentation on similar problems in the SWIG documentation, but I haven't had any luck implementing a solution. I've also looked into some other stackoverflow questions (this one seems suspiciously close), also to no avail. I suspect that I should use a typemap here, but am young and foolish when it comes to SWIG.

Any suggestions or pointers?

Many thanks.

2
  • have you tried creating an overload float* GetAttOrder(int node, DCE_ORDER order) which calls your GetAttOrder? I believe SWIG knows how to treat a pointer return as a Python list. Commented May 3, 2014 at 11:29
  • No I hadn't tried that, but I did end up getting something to work. I'll go ahead and answer myself. Commented May 4, 2014 at 15:16

1 Answer 1

2

Ended up solving this a couple days later. If you have a vector that you want to get out you can do something like:

%typemap(in, numinputs=0) float vec3out[3] (float temp[3]) {
  $1 = temp;
}

%typemap(argout) float vec3out[3] {
  int i;
  $result = PyList_New(3);
  for (i = 0; i < 3; i++) {
    PyObject *o = PyFloat_FromDouble((double) $1[i]);
    PyList_SetItem($result,i,o);
  }
}

And then can access this function through Python as I requested above. Additionally, if you have another function that you want to pass a list into (a getter/setter pair of functions), you can use the following code:

%typemap(in) float vec3in[3] (float temp[3]) {
  int i;
  if (!PySequence_Check($input)) {
    PyErr_SetString(PyExc_ValueError,"Expected a sequence");
    return NULL;
  }
  if (PySequence_Length($input) != 3) {
    PyErr_SetString(PyExc_ValueError,"Size mismatch. Expected 3 elements");
    return NULL;
  }
  for (i = 0; i < 3; i++) {
    PyObject *o = PySequence_GetItem($input,i);
    if (PyNumber_Check(o)) {
      temp[i] = (float) PyFloat_AsDouble(o);
    } else {
      PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers");
      return NULL;
    }
  }
  $1 = temp;
}

which would allow you to pass in a list.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.