更改 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 包装函数返回值的主要内容,如果未能解决你的问题,请参考以下文章