Discussion:
Swig, Java and default arguments
G***@ubsw.com
2003-02-27 10:26:37 UTC
Permalink
Hi,
I am successfully using Swig to wrap a C++ class hierarchy into a Java class hierarchy, using Swig 1.3.17

Concerning default arguments....

If I have a class member function like

void f(int i1, int i2 = 0); //the second int has a default value

the equivalent C wrapped function has something like

...
int arg3 = (int) 0; //where arg3 corresponds to my i2
...
arg3 = (int) jarg3; //!oops loosing the default value

Am I missing something on the default args mechanism?

I understand that this might be an issue with simple types (int), but the same happens if the argument is an object passed by value or reference. There is no check if the JNI argument is null (which could be used to represent defaults) or not. Eventually the default value is always lost.
At best an exception is thrown.

Is there any way to use effectively the default argument mechanism?

Thanks for your help.

Gualtiero Chiaia
UBS Warburg - London

Visit our website at http://www.ubswarburg.com

This message contains confidential information and is intended only
for the individual named. If you are not the named addressee you
should not disseminate, distribute or copy this e-mail. Please
notify the sender immediately by e-mail if you have received this
e-mail by mistake and delete this e-mail from your system.

E-mail transmission cannot be guaranteed to be secure or error-free
as information could be intercepted, corrupted, lost, destroyed,
arrive late or incomplete, or contain viruses. The sender therefore
does not accept liability for any errors or omissions in the contents
of this message which arise as a result of e-mail transmission. If
verification is required please request a hard-copy version. This
message is provided for informational purposes and should not be
construed as a solicitation or offer to buy or sell any securities or
related financial instruments.
William S Fulton
2003-02-27 22:55:39 UTC
Permalink
Post by G***@ubsw.com
Hi,
I am successfully using Swig to wrap a C++ class hierarchy into a Java class hierarchy, using Swig 1.3.17
Concerning default arguments....
If I have a class member function like
void f(int i1, int i2 = 0); //the second int has a default value
the equivalent C wrapped function has something like
...
int arg3 = (int) 0; //where arg3 corresponds to my i2
...
arg3 = (int) jarg3; //!oops loosing the default value
Am I missing something on the default args mechanism?
I understand that this might be an issue with simple types (int), but the same happens if the argument is an object passed by value or reference. There is no check if the JNI argument is null (which could be used to represent defaults) or not. Eventually the default value is always lost.
At best an exception is thrown.
Is there any way to use effectively the default argument mechanism?
Default args havn't really been dealt with in the Java module, so I'm
open to suggestions on how to make use of them. Right now you could
write a typemap which would do something along the lines of what you
want to produce code like this:

...
int arg3 = (int) 0; //where arg3 corresponds to my i2
...
if (jarg3 != some_special_value)
arg3 = (int) jarg3;

Seems like bit of a hack, but will work if you write specific typemaps
for specific named parameters. One couldn't use a Java null all the time
as one can't use this if the type is a primitive type like int.

The typemap you'll need to achieve the above ...

%typemap(in) int i2 %{
if ($input != some_special_value) {
$1 = (int)$input;
}
%}


A more robust solution could be implemented in a later version of SWIG
which would generate an overloaded Java method for each C++ function
with default values ...

void f(int i1) { ... } // Calls f with default i2 = 0
void f(int i1, int i2) { ... }

It might get a bit messy implementing the JNI function. Maybe the in
typemap would have to be ignored in the one function.

Cheers
William
G***@ubsw.com
2003-02-28 09:22:15 UTC
Permalink
William,
thank you for your quick reply!

It seems that we have been mind reading each other. After I posted my message and before your reply I came out with a hack that is almost "verbatim" yours.
I have created some swig macro for different categories of default parameters (for the time being I only need const references parameters and reference parameters). I wrapped these macro in a interface file:

file default_args.i

/****************************************************
* Sets of macro for default arguments (needed in Java)
* by Gualtiero Chiaia
*****************************************************/

//used for default const reference arguments
%define DEFAULT_CONST_REFERENCE(TYPE,NAME,DEF)
%typemap(in) const TYPE& NAME (TYPE tmp)%{
tmp = DEF;
if ($input) $1 = *(TYPE**)&$input;
else $1 = &tmp;
%}
%enddef

//used for default reference arguments
%define DEFAULT_REFERENCE(TYPE,NAME,DEF)
%typemap(in) TYPE& NAME (TYPE tmp) %{
tmp = DEF;
if ($input) $1 = *(TYPE**)&$input;
else $1 = &tmp;
%}
%enddef

and then I use these macro in the following way, before a member function that requires def parameters.

For example:

<<
DEFAULT_CONST_REFERENCE(FIA_Phi::Rounding,accrualRounding_d,FIA_Phi::Rounding())
DEFAULT_CONST_REFERENCE(FIA_Phi::BondBasis,repoDayCount_d,FIA_Phi::BondBasis())
DEFAULT_REFERENCE(FIA_Phi::BondDateCtx,exDividendConvention_d,FIA_Phi::BondDateCtx())
DEFAULT_CONST_REFERENCE(FIA_Phi::PriceCalcMethod,priceCalculationMethod_d,FIA_Phi::PriceCalcMethod())
DEFAULT_CONST_REFERENCE(FIA_Phi::LinearLastPeriods,linearLastPeriods_d,FIA_Phi::LinearLastPeriods())
DEFAULT_CONST_REFERENCE(FIA_Phi::AmountAdjustment,amountAdjustment_d,FIA_Phi::AmountAdjustment())
DEFAULT_CONST_REFERENCE(FIA_Phi::DateAdjustment,dateAdjustment_d,FIA_Phi::DateAdjustment())
DEFAULT_CONST_REFERENCE(FIA_Utilities::Date,validFromDate_d,FIA_Utilities::Date())
DEFAULT_CONST_REFERENCE(FIA_Utilities::Date,validToDate_d,FIA_Utilities::Date())
DEFAULT_CONST_REFERENCE(FIA_Phi::DayReference,regularCpnPayment_d,FIA_Phi::DayReference())

BondConvention(
const std::string& bondType,
const BondFreq& couponFrequency,
const BondBasis& accrualDayCount,
const SettlementConv& settlementConvention,
const YieldCalcMethod& yieldCalculationMethod,
const std::string& currency_d,
const Rounding& accrualRounding_d,
const BondBasis& repoDayCount_d,
BondDateCtx& exDividendConvention_d,
const PriceCalcMethod& priceCalculationMethod_d,
const LinearLastPeriods& linearLastPeriods_d,
const AmountAdjustment& amountAdjustment_d,
const DateAdjustment& dateAdjustment_d,
const FIA_Utilities::Date& validFromDate_d,
const FIA_Utilities::Date& validToDate_d,
const DayReference& regularCpnPayment_d
);
Each macro has 3 parameters
1) the class of the parameter
2) the name of the input parameter
3) the default value

It works fine for the time being, although only for objects and not for primitive types.
For object I then use a null pointer in the Java API to specify a default parameter:

e.g.

BondConvention bc1 = new BondConvention("GILT",new BondFreq("a"),new BondBasis("ACT/ACT"),
new SettlementConv(),
new YieldCalcMethod(YieldCalcMethod.eNone,
BondFreq.eNone,
BondBasis.eNONE),
"",null,null,null,null,null,null,null,
null,null,null);

I guess for primitive types (e.g. int) the only solution would be to produce as many function signatures as combination of parameters.

Thanks again for your help.

Gualtiero

-----Original Message-----
From: William S Fulton [mailto:***@fultondesigns.co.uk]
Sent: 27 February 2003 22:56
To: Chiaia, Gualtiero
Cc: swig-***@cs.uchicago.edu
Subject: Re: [Swig-dev] Swig, Java and default arguments
Post by G***@ubsw.com
Hi,
I am successfully using Swig to wrap a C++ class hierarchy into a Java class hierarchy, using Swig 1.3.17
Concerning default arguments....
If I have a class member function like
void f(int i1, int i2 = 0); //the second int has a default value
the equivalent C wrapped function has something like
...
int arg3 = (int) 0; //where arg3 corresponds to my i2
...
arg3 = (int) jarg3; //!oops loosing the default value
Am I missing something on the default args mechanism?
I understand that this might be an issue with simple types (int), but the same happens if the argument is an object passed by value or reference. There is no check if the JNI argument is null (which could be used to represent defaults) or not. Eventually the default value is always lost.
At best an exception is thrown.
Is there any way to use effectively the default argument mechanism?
Default args havn't really been dealt with in the Java module, so I'm
open to suggestions on how to make use of them. Right now you could
write a typemap which would do something along the lines of what you
want to produce code like this:

...
int arg3 = (int) 0; //where arg3 corresponds to my i2
...
if (jarg3 != some_special_value)
arg3 = (int) jarg3;

Seems like bit of a hack, but will work if you write specific typemaps
for specific named parameters. One couldn't use a Java null all the time
as one can't use this if the type is a primitive type like int.

The typemap you'll need to achieve the above ...

%typemap(in) int i2 %{
if ($input != some_special_value) {
$1 = (int)$input;
}
%}


A more robust solution could be implemented in a later version of SWIG
which would generate an overloaded Java method for each C++ function
with default values ...

void f(int i1) { ... } // Calls f with default i2 = 0
void f(int i1, int i2) { ... }

It might get a bit messy implementing the JNI function. Maybe the in
typemap would have to be ignored in the one function.

Cheers
William


Visit our website at http://www.ubswarburg.com

This message contains confidential information and is intended only
for the individual named. If you are not the named addressee you
should not disseminate, distribute or copy this e-mail. Please
notify the sender immediately by e-mail if you have received this
e-mail by mistake and delete this e-mail from your system.

E-mail transmission cannot be guaranteed to be secure or error-free
as information could be intercepted, corrupted, lost, destroyed,
arrive late or incomplete, or contain viruses. The sender therefore
does not accept liability for any errors or omissions in the contents
of this message which arise as a result of e-mail transmission. If
verification is required please request a hard-copy version. This
message is provided for informational purposes and should not be
construed as a solicitation or offer to buy or sell any securities or
related financial instruments.
William S Fulton
2003-02-28 19:44:50 UTC
Permalink
Would it take long to get $1_type and friends working in typemaps when
they are used for local variable declarations:

%typemap(whatever) long long($1_type temp) " ... "

I'd like this for using some typemaps for %apply, as currently if one uses

%apply long long {LongLong}
%typemap(whatever) long long(long long temp) " ... "

it won't compile on systems that don't support long long as SWIG generates:

long long temp;

and what is needed is:

LongLong temp;

Cheers
William
David Beazley
2003-02-28 20:36:39 UTC
Permalink
Post by William S Fulton
Would it take long to get $1_type and friends working in typemaps when
%typemap(whatever) long long($1_type temp) " ... "
I'd like this for using some typemaps for %apply, as currently if one uses
%apply long long {LongLong}
%typemap(whatever) long long(long long temp) " ... "
long long temp;
LongLong temp;
I thought this worked already. Am I missing something?

Cheers,
Dave
William S Fulton
2003-02-28 23:21:23 UTC
Permalink
Post by David Beazley
Post by William S Fulton
Would it take long to get $1_type and friends working in typemaps when
%typemap(whatever) long long($1_type temp) " ... "
I'd like this for using some typemaps for %apply, as currently if one uses
%apply long long {LongLong}
%typemap(whatever) long long(long long temp) " ... "
long long temp;
LongLong temp;
I thought this worked already. Am I missing something?
Hmmm, I've been scratching my head here trying different combinations as
it seemed to work for one test case but not another. I think I've nailed
the pattern though and it doesn't have anything to do with %apply...

This fails (doesn't replace $1_type with long long):
%typemap(in) long long($1_type temp) " /* */ "

These work:
%typemap(in) long long($1_type temp) " /* $1_type */ "
%typemap(in) long long($1_type temp) " /* $&1_type */ "

Cheers
William
David Beazley
2003-03-03 17:39:13 UTC
Permalink
Post by William S Fulton
Post by David Beazley
I thought this worked already. Am I missing something?
Hmmm, I've been scratching my head here trying different combinations as
it seemed to work for one test case but not another. I think I've nailed
the pattern though and it doesn't have anything to do with %apply...
%typemap(in) long long($1_type temp) " /* */ "
%typemap(in) long long($1_type temp) " /* $1_type */ "
%typemap(in) long long($1_type temp) " /* $&1_type */ "
Maybe the typemap code is looking for an occurrence of the pattern
before doing any replacements. I'll take a look at it.

Cheers,

Dave

Loading...