5

Update

I have just found out about the %apply directive (see here for instance). Unfortunately I can't make it work with structs:

%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"

This results in:

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

I can't find any documentation whatsoever about this warning. It looks like I have to define a custom typemap, but I have no idea where to start. I'm growing pretty tired of this lack of documentation, and pretty desperate of one day succeeding in writing my wrapper :(

Original post

Following my two previous posts, I still have problems using a C library in C#.

To recap: I have a C library, and I'm trying to write a C# wrapper using Swig.

In the .h file, the method is declared such:

int pack(image_t *images, int nb_images, parameters_t params);

Actually the *images is always passed an array. If I just generate swig files like this, in the C# files, the function expects a single instance:

  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;
  }

So, following this comment, I have modified my .i file such :

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

Now I can build my "fake" array using the new_image_t_array and image_t_array_setitem methods, but when I run my test program, it throws a System.AccessViolationException (it's trying to "read or write protected memory") on the pack method call (C# program):

// 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);

Actually, the exception is thrown at the int ret = packer_csPINVOKE.pack(image_t.getCPtr(images), nb_images, parameters_t.getCPtr(arg2)); line in the C# file generated by Swig.

Any idea as to why this is happening ? As I said in my other posts, I know nothing about C/C++, pointers and stuff, so it may be obvious...

Thanks !

Community
  • 1
  • 1
thomasb
  • 5,816
  • 10
  • 57
  • 92

1 Answers1

1

I don't know if it matters, can't test, but Your .i might have to export the pack function after the array_functions:

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

Also, nothing forces you to declare the exact same signature. You can probably have something like this:

%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);

The wrapper code will call the C version of pack, giving it the array, this is ok because the function takes a pointer to image_t and C knows how to works with array as pointer.

Update: Since the above didn't help, I took at look at arrays_csharp.i: it calls CSHARP_ARRAYS and CSHARP_ARRAYS_FIXED macro on all basic types, and the .i of the arrays example that is included with SWIG calls the apply nonetheless so it may be that %apply does not do this automatically. In fact, it looks like these two macros are the typemaps, so I think it is worth a try:

%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"
Oliver
  • 27,510
  • 9
  • 72
  • 103
  • The first thing (order of include/array_functions) doesn't matter, it just changes the order of declaration of methods in the generated c# files. The switch to an array changes nothing, because Swig switches arrays to pointers internally :( – thomasb Jun 30 '14 at 07:33
  • AWESOME thank you so much! It still has the memory access problem, but now I can pass the array directly ! :) I used INOUT[] but still no luck :( Since the original question was about passing an array, I'll mark you as answer, even though I still have my problem :( – thomasb Jul 01 '14 at 07:35
  • If you ever feel like it, my follow-up question is here: http://stackoverflow.com/questions/24505629/using-structs-inside-structs-with-swig :) – thomasb Jul 01 '14 at 09:48