On 2 October 2013 14:51, Vadim Zeitlin <vz-swig@zeitlins.org> wrote:

Hello,

This is another weird bug report which only I seem to be encountering (not

intentionally, believe me). Please consider this example:

% cat -n et.i

1 %module et

2

3 template <typename T> struct T {};

4

5 %naturalvar T<E>;

6 %template(TE) T<E>;

7

8 %inline { enum E { E1, E2, E3 }; }

9

10 %typemap(csvarout, excode=SWIGEXCODE2) const T<E>& %{

11 get {

12 // Intentionally don't use excode here to trigger a warning if this

13 // typemap is used.

14 return $imcall;

15 }%}

16

17 %inline {

18 struct S {

19 T<E> ee;

20 };

21 }

This works as expected, i.e.

% swig -csharp -c++ -o wrap_et_csharp.cpp et.i

et.i:19: Warning 844: C# exception may not be thrown - no $excode or excode attribute in 'csvarout' typemap.

As the warning indicates, the typemap is used and everything is fine.

Now exchange the line #8, with the enum declaration, and the line #6 and

rerun swig. Now the typemap is not used any more. And there doesn't seem to

be any way to make SWIG handle "ee" naturally if the enum declaration comes

before the %template line short of using either "-naturalvar" command line

option or parameter-less "%naturalvar" (which both result in other problems

elsewhere in my code and so I'd like to avoid them).

I've tried all the possible orders of the different lines keeping the enum

declaration at the top (again, because this is where it appears in my real

code and it's not trivial to change this as enum comes from a header

included from another header from another module...) without success. I

also tried using "%naturalvar TE" in desperation but it doesn't work

neither (which is at least somewhat reassuring). Conversely, any order with

%template coming before the enum declaration does work.

This definitely looks like a bug in SWIG to me, especially because if you

replace "enum E { ... }" with "struct E {}", everything works just fine, in

whatever order. But, as usual, I have absolutely no idea where to start

looking for it.

Any hints/ideas?

The -debug-tmsearch option is really useful for this kind of problem. In the first case, you'll see:

example.i:22: Searching for a suitable 'csvarout' typemap for: T< E > const &S::ee

Looking for: T< E > const &S::ee

Looking for: T< E > const &ee

Looking for: T< E > const &

Using: %typemap(csvarout) T< E > const &

indicating your typemap is being used as you observed. Swapping lines #6 and #8 gives:

example.i:22: Searching for a suitable 'csvarout' typemap for: T< E > *S::ee

Looking for: T< E > *S::ee

Looking for: T< E > *ee

Looking for: T< E > *

Looking for: T *S::ee

Looking for: T *ee

Looking for: T *

Looking for: T< enum E > *S::ee

Looking for: T< enum E > *ee

Looking for: T< enum E > *

Looking for: T *S::ee

Looking for: T *ee

Looking for: T *

Looking for: SWIGTYPE *S::ee

Looking for: SWIGTYPE *ee

Looking for: SWIGTYPE *

Using: %typemap(csvarout) SWIGTYPE *

Which should explain why your typemap is not being found - %naturalvar is not having any effect and it is looking for a different type. It gives a clue as to what to do to fix though, change line #10 to:

%typemap(csvarout, excode=SWIGEXCODE2) const T<E>&, T<E>* %{

then you get a match, tada!

example.i:22: Searching for a suitable 'csvarout' typemap for: T< E > *S::ee

Looking for: T< E > *S::ee

Looking for: T< E > *ee

Looking for: T< E > *

Using: %typemap(csvarout) T< E > *

Quite why T<E>* is required instead of const T<E>& even though you have %naturalvar, is not clear to me without looking further into %naturalvar with enums.

William