change SWIG wrapper-function return value
I'm using SWIG to make C# bindings that are compatible with the compact framework (WinCE). I've got most of the immediate issues worked through, but my next blocker is that some of the functions return a double. Wrappers are generated but they fail at run time because the CF framework will not marshal non-integral datatypes (http://msdn.microsoft.com/en-us/library/aa446536.aspx)
My example failure is an attempt to wrap this function:
double getMaxMagnification() const
{
return m_maxMag;
}
SWIG generates this wrapper:
SWIGEXPORT double SWIGSTDCALL CSharp_LTIImageFilter_getMaxMagnification(void * jarg1) {
double jresult ;
LizardTech::LTIImageFilter *arg1 = (LizardTech::LTIImageFilter *) 0 ;
double result;
arg1 = (LizardTech::LTIImageFilter *)jarg1;
result = (double)((LizardTech::LTIImageFilter const *)arg1)->getMaxMagnification();
jresult = result;
return jresult;
}
which is NG because it requires marshalling a double return value.
I manually changed this to return the double via a passed-in pointer:
SWIGEXPORT void SWIGSTDCALL CSharp_LTIImageFilter_getMaxMagnification(void * jarg1, void *jar开发者_开发问答g2) {
fprintf(stderr, "CSharp_LTIImageFilter_getMaxMagnification\n");
//double jresult ;
LizardTech::LTIImageFilter *arg1 = (LizardTech::LTIImageFilter *) 0 ;
double result;
arg1 = (LizardTech::LTIImageFilter *)jarg1;
result = (double)((LizardTech::LTIImageFilter const *)arg1)->getMaxMagnification();
*((double*)jarg2) = result;
//jresult = result ;
//return jresult;
}
After making the corresponding changes in the C# declaration file and implementation class, this works as expected.
That is,
Interop Declaration
NG:
[DllImport("LizardTech_SdkInterop.dll", EntryPoint="CSharp_LTIImageFilter_getMaxMagnification")]
public static extern double LTIImageFilter_getMaxMagnification(IntPtr jarg1);
OK:
[DllImport("LizardTech_SdkInterop.dll", EntryPoint="CSharp_LTIImageFilter_getMaxMagnification")]
public static extern void LTIImageFilter_getMaxMagnification(IntPtr jarg1, ref double jarg2);
Implementation class
NG:
public override double getMaxMagnification() {
double ret = RasterSDKPINVOKE.LTIImageFilter_getMaxMagnification(swigCPtr);
return ret;
}
OK:
public override double getMaxMagnification() {
double ret = 0;
RasterSDKPINVOKE.LTIImageFilter_getMaxMagnification(swigCPtr, ref ret);
return ret;
}
How can I get SWIG to do this for me? I think the tasks are:
(a) change the return type of the wrapper function (only) from double to void (b) add an argument (pointer to double) to the argument list so that the wrapper can send back the value that way (c) make the interop declaration reflect the above two changes (d) make the C# wrapper invoke the new wrapper function.
As always big-picture re-orientation is appreciated.
I'm indebted to David Piepgrass for this. It's not perfect but its good enough for me.
http://sourceforge.net/mailarchive/message.php?msg_id=26952332
////////////////////////////////////////////////////////////////////////////////
// Floating-point value marshalling for .NET Compact Framework:
// All floating-point values must be passed by reference. MULTITHREADING DANGER:
// For return values a pointer to a static variable is returned.
%define %cs_compact_framework_float(FLOAT)
%typemap(ctype, out="FLOAT*") FLOAT "FLOAT*"
%typemap(ctype, out="FLOAT*") FLOAT*, FLOAT&, const FLOAT& "FLOAT*"
%typemap(imtype, out="IntPtr") FLOAT, FLOAT*, FLOAT&, const FLOAT& "ref FLOAT"
%typemap(cstype, out="FLOAT") FLOAT, const FLOAT& "FLOAT"
%typemap(cstype, out="FLOAT") FLOAT*, FLOAT& "ref FLOAT"
%typemap(in) FLOAT %{ $1 = *$input; %}
%typemap(in) FLOAT*, FLOAT&, const FLOAT& %{ $1 = $input; %}
%typemap(out, null="NULL") FLOAT, FLOAT*, FLOAT&, const FLOAT& %{
// Not thread safe! FLOAT must be returned as a pointer in Compact Framework
static FLOAT out_temp;
out_temp = $1;
$result = &out_temp;
%}
%typemap(csin) FLOAT, const FLOAT& "ref $csinput"
%typemap(csin) FLOAT*, FLOAT& "ref $csinput"
%typemap(csout, excode=SWIGEXCODE) FLOAT, FLOAT*, FLOAT&, const FLOAT& {
IntPtr ptr = $imcall;$excode
FLOAT ret = (FLOAT)Marshal.PtrToStructure(ptr, typeof(FLOAT));
return ret;
}
%typemap(csvarout, excode=SWIGEXCODE2) FLOAT, FLOAT*, FLOAT&, const FLOAT&
%{
get {
IntPtr ptr = $imcall;$excode
FLOAT ret = (FLOAT)Marshal.PtrToStructure(ptr, typeof(FLOAT));
return ret;
}
%}
%enddef
%cs_compact_framework_float(float)
%cs_compact_framework_float(double)
精彩评论