更改SWIG包装函数返回值

时间:2011-01-22 02:33:17

标签: swig

我正在使用SWIG制作与紧凑框架(WinCE)兼容的C#绑定。我已经解决了大部分直接问题,但我的下一个阻止是某些函数返回了一个双精度函数。生成包装器但它们在运行时失败,因为CF框架不会封送非整数数据类型(http://msdn.microsoft.com/en-us/library/aa446536.aspx)

我的示例失败是尝试包装此函数:

   double getMaxMagnification() const
   {
      return m_maxMag;
   }

SWIG生成此包装器:

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;
}

这是NG,因为它需要编组双返回值。

我手动更改了这个以通过传入的指针返回double:

SWIGEXPORT void SWIGSTDCALL CSharp_LTIImageFilter_getMaxMagnification(void * jarg1, void *jarg2) {
  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;
}

在C#声明文件和实现类中进行相应的更改后,这将按预期工作。

即,

互操作声明

NG:

  [DllImport("LizardTech_SdkInterop.dll", EntryPoint="CSharp_LTIImageFilter_getMaxMagnification")]
  public static extern double LTIImageFilter_getMaxMagnification(IntPtr jarg1);

行:

 [DllImport("LizardTech_SdkInterop.dll", EntryPoint="CSharp_LTIImageFilter_getMaxMagnification")]
  public static extern void LTIImageFilter_getMaxMagnification(IntPtr jarg1, ref double jarg2);

实施班

NG:

  public override double getMaxMagnification() {
    double ret = RasterSDKPINVOKE.LTIImageFilter_getMaxMagnification(swigCPtr);
    return ret;
  }

行:

public override double getMaxMagnification() {
    double ret = 0;
    RasterSDKPINVOKE.LTIImageFilter_getMaxMagnification(swigCPtr, ref ret);
    return ret;
  }

我如何让SWIG为我这样做?我认为任务是:

(a)将包装函数(仅)的返回类型从double更改为void (b)向参数列表添加一个参数(指向double的指针),以便包装器可以通过该方式发回值 (c)使互操作声明反映上述两个变化 (d)使C#包装器调用新的包装函数。

一如既往地重新定位大画面。

1 个答案:

答案 0 :(得分:1)

我非常感谢David Piepgrass。它并不完美,但对我来说已经足够了。

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)