更改 SWIG 包装函数返回值

Posted

技术标签:

【中文标题】更改 SWIG 包装函数返回值【英文标题】:change SWIG wrapper-function return value 【发布时间】:2011-01-22 02:33:16 【问题描述】:

我正在使用 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,因为它需要编组一个双返回值。

我手动将其更改为通过传入的指针返回双精度:

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) 向参数列表添加一个参数(指向双精度的指针),以便包装器可以以这种方式发回值 (c) 使互操作声明反映上述两个变化 (d) 使 C# 包装器调用新的包装器函数。

一如往常,大图重新定位是值得赞赏的。

【问题讨论】:

【参考方案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)

【讨论】:

以上是关于更改 SWIG 包装函数返回值的主要内容,如果未能解决你的问题,请参考以下文章

用于包装无符号二进制数据的 SWIG 技术

Python SWIG:将 C++ 返回参数转换为返回值,并将原始 C++ 类型转换为 Python 类型

带有 SWIG 未知长度数组的 NumPy C 扩展

用 SWIG array_class 包装字节数组数据

使用python包装的c ++ SWIG模拟输入

SWIG:如何使用 %apply 返回结构? “未定义类型映射”警告