如何使用 swig 从`unsigned int *`返回`uint []`
Posted
技术标签:
【中文标题】如何使用 swig 从`unsigned int *`返回`uint []`【英文标题】:How to return `uint []` from `unsigned int *` using swig 【发布时间】:2019-07-16 07:30:44 【问题描述】:我必须包装以下 c++ 函数:
class Foo
unsigned int *getVector3();
;
成员函数getVector3
,返回一个(固定的)3D 数组,例如[1,2,3]
。我应该如何使用 arrays_csharp.i
作为返回类型?该文档仅描述了输入参数:
在我的例子中,返回类型始终是一个固定大小的数组(3 个元素)。
【问题讨论】:
【参考方案1】:我有一个答案,尽管在我看来并不完全令人满意。不过,这主要受限于我对 C# 的了解,因此您可能会比我做得更好。
我不认为 arrays_csharp 是你在这里寻找的。这似乎是关于固定内存,因此它可以用作函数的输入,但在您的场景中,您已经分配了您想要使用的内存。
正常使用 System.InteropServices.Marshal 相当简单(而且对于 3D 矢量来说非常便宜)。因此,我使用了一些类型映射来满足您的需求:
%module test
%typemap(csout,excode=SWIGEXCODE) unsigned *getVector
global::System.IntPtr cPtr = $imcall;$excode
int[] tmp = new int[3];
// I have no idea why Marshal.Copy does not seem to have any support for unsigned types...
global::System.Runtime.InteropServices.Marshal.Copy(cPtr, tmp, 0, 3);
// There is probably a better way to go from int[3] -> uint[3], but it is not obvious to me
return new $typemap(cstype, $*1_type)[3]($typemap(cstype, $*1_type))tmp[0],($typemap(cstype, $*1_type))tmp[1],($typemap(cstype, $*1_type))tmp[2];
%typemap(cstype) unsigned *getVector "$typemap(cstype, $*1_type)[]"
%inline %
unsigned *getVector()
static unsigned arr[3] = 1,2,3;
return arr;
%
不过有几点说明:
$typemap(cstype, $*1_type)
是一种奇特的说法,即找到与我的 C 元素类型相对应的 C# 类型。我倾向于尝试避免在类型映射中显式编写类型,因为它会使事情更通用。
话虽如此,Marshal.Copy
似乎只适用于有符号而不是无符号数组类型,原因我不太清楚。而且我看不到一种自动方法来为无符号类型找到相应的有符号类型,所以我必须明确写 int[]
我不确定有符号 -> 无符号转换实际上是 C# 中明确定义的行为。对于设置了最后一位的值,这可能无法正常工作。您可以通过增加tmp
的int
类型的大小来解决此问题。 (例如,使用int64
而不是int32
,但这并不漂亮)
应该有比我所做的更好的方法来转换整个数组,但我不太了解 C# 语言。
也就是说,我可以运行以下程序(使用 Mono)并获得预期的输出
public class runme
static void Main(string[] args)
uint[] arr = test.getVector();
System.Console.WriteLine(arr[0]);
System.Console.WriteLine(arr[1]);
System.Console.WriteLine(arr[2]);
如果有用的话,我们可以做更多的工作来使这个通用(即其他大小向量、其他数据类型int16[4]
等)。
【讨论】:
以上是关于如何使用 swig 从`unsigned int *`返回`uint []`的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Swig 将 unsigned char* 转换为 Python 列表?
使用 SWIG 时如何将 int 数组和 List<string> 作为参数从 C# 传递给 C++
TypeError:在方法“...”中,使用 swig 模块时类型为“unsigned char const *”的参数 1