如何使用swig从unsigned int *中返回uint []

时间:2019-07-16 07:30:44

标签: c# c++ swig

我必须包装以下c ++函数:

class Foo {
  unsigned int *getVector3();
};

成员函数getVector3返回一个(固定的)3D数组,例如[1,2,3]。如何将arrays_csharp.i用作返回类型?该文档仅描述输入参数:

在我的情况下,返回类型始终是一个固定大小的数组(包含3个元素)。

1 个答案:

答案 0 :(得分: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#中定义良好的行为。对于设置了最后一位的值,这可能无法正常工作。您可以通过增加int的{​​{1}}类型的大小来解决此问题。 (例如,使用tmp代替int64,但这不是很漂亮)
  • 应该有比我做的更好的方法来投射整个数组,但我不太了解C#语言。

那已经足够我可以运行以下程序(使用Mono)并获得预期的输出

int32

如果有用的话,我们可以做更多的工作来使这个通用(即其他大小向量,其他数据类型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]); } } 等)。