Swig - 生成包装器以传递结构数组

tho*_*asb 5 c c# swig

更新

我刚刚发现了有关该%apply指令的信息(例如,请参见此处)。不幸的是,我不能让它与结构一起工作:

%module packer_cs
%include "carrays.i"
%{
    #include "packer.h" 
%}
%include "typemaps.i"
%include "arrays_csharp.i"
%apply image_t INPUT[] { image_t *images }
%include "packer.h"
Run Code Online (Sandbox Code Playgroud)

这导致:

swig -csharp -outdir bin\csharp packer\packer.i
Warning 453: Can't apply (image_t INPUT[]). No typemaps are defined.
Run Code Online (Sandbox Code Playgroud)

我找不到有关此警告的任何文档。看起来我必须定义一个自定义类型映射,但我不知道从哪里开始。我对文档的缺乏越来越厌倦,并且非常渴望有一天能够成功地编写我的包装器:(

原帖

按照我之前的两篇 文章,我在 C# 中使用 C 库仍然有问题。

回顾一下:我有一个 C 库,我正在尝试使用 Swig 编写一个 C# 包装器。

在 .h 文件中,该方法声明如下:

int pack(image_t *images, int nb_images, parameters_t params);
Run Code Online (Sandbox Code Playgroud)

实际上*images总是传递一个数组。如果我只是像这样生成 swig 文件,在 C# 文件中,该函数需要一个实例:

  public static int pack(image_t images, int nb_images, parameters_t arg2) {
    int ret = packer_csPINVOKE.pack(image_t.getCPtr(images), nb_images, parameters_t.getCPtr(arg2));
    if (packer_csPINVOKE.SWIGPendingException.Pending) throw packer_csPINVOKE.SWIGPendingException.Retrieve();
    return ret;
  }
Run Code Online (Sandbox Code Playgroud)

因此,在此评论之后,我修改了我的 .i 文件,例如:

%module packer_cs
%include <carrays.i>
%{
    #include "packer.h" 
%}
%include "packer.h"
%array_functions(image_t, image_t_array);
Run Code Online (Sandbox Code Playgroud)

现在我可以使用new_image_t_arrayimage_t_array_setitem方法构建我的“假”数组,但是当我运行我的测试程序时,它会System.AccessViolationExceptionpack方法调用(C# 程序)上抛出一个(它正在尝试“读取或写入受保护的内存” ):

// the "images" variable is a List<image_t>
var images_array = packer_cs.new_image_t_array(images.Count);
for (var i = 0; i < images.Count; i++)
{
    packer_cs.image_t_array_setitem(images_array, i, images[i]);
}

// this throws the exception
var result = packer_cs.pack(images_array, images.Count, param);
Run Code Online (Sandbox Code Playgroud)

实际上,异常是在int ret = packer_csPINVOKE.pack(image_t.getCPtr(images), nb_images, parameters_t.getCPtr(arg2));Swig 生成的 C# 文件中的行中引发的。

知道为什么会这样吗?正如我在其他帖子中所说,我对 C/C++、指针和其他东西一无所知,所以这可能很明显......

谢谢 !

Oli*_*ver 1

我不知道这是否重要,无法测试,但是您的 .i 可能必须pack在 array_functions 之后导出该函数:

%module packer_cs
%include <carrays.i>
%{
    #include "packer.h" 
%}
%array_functions(image_t, image_t_array);
%include "packer.h"
Run Code Online (Sandbox Code Playgroud)

此外,没有什么会强迫您声明完全相同的签名。你可能可以有这样的东西:

%module packer_cs
%include <carrays.i>
%{
    #include "packer.h" 
%}

// export image_t and parameters_t, then: 
int pack(image_t images[], int nb_images, parameters_t params);
Run Code Online (Sandbox Code Playgroud)

包装器代码将调用 C 版本的 pack,为其提供数组,这是可以的,因为该函数采用指向 image_t 的指针,并且 C 知道如何将数组用作指针。

更新:由于上述内容没有帮助,我查看了arrays_csharp.i:它在所有基本类型上调用CSHARP_ARRAYSCSHARP_ARRAYS_FIXED宏,并且 SWIG 中包含的数组示例的 .i 仍然调用,apply因此可能%apply不会执行此操作自动地。事实上,看起来这两个宏就是类型映射,所以我认为值得一试:

%module packer_cs
%include "carrays.i"
%{
    #include "packer.h" 
%}
%include "typemaps.i"
%include "arrays_csharp.i"
CSHARP_ARRAYS(image_t, image_t)
CSHARP_ARRAYS_FIXED(image_t, image_t)
%apply image_t INPUT[] { image_t *images }
%include "packer.h"
Run Code Online (Sandbox Code Playgroud)