Reputation: 506
I maintain a C++ SDK that now needs to be converted to other languages (specifically C# and Java). I am using SWIG to generate my wrapper code and successfully have completed the Java work. I now need to get C# working.
I have a C++ function (ignore the Header
object in the function signature - I have that worked out already)
int send(Header header, char *payload);
Furthermore, I have a director
class in C++ that is as follows:
class Callbacks {
public:
virtual ~Callbacks() { }
virtual void receive(Header header, char *payload) { }
};
Which allows me to create callbacks in my Java and C# code.
I need the following function signatures for send
and receive
in C#:
int send(Header header, byte[] payload);
and
void receive(Header header, byte[] payload);
Typemaps in SWIG seem to be the way to go so here was my attempt at typemapping for C#:
%module(directors="1") example
%{
#include "example.h"
%}
%feature("director") Callbacks;
%include "arrays_csharp.i"
CSHARP_ARRAYS(char, byte)
%typemap(imtype, inattributes="[In, MarshalAs(UnmanagedType.LPArray, SizeConst=2048, ArraySubType=UnmanagedType.U1)]") char INPUT[] "byte[]"
%apply char INPUT[] {char *payload}
%include "example/include/example.h"
The results of that interface file gets my desired function signatures but my byte arrays are only size 1 and I only get the first item in my original char buffers. It seems as if SWIG interpreted the char* as a pointer to a char and therefore stuck the first element in my char* buffer into a byte array and called it good. But I would like to create a byte array of size 2048 (no payload will have a size greater than that) and fill that byte array from the char* buffer. If it makes any difference, my Header
class object has the size of the char* buffer but I really could care less about that right now and stick with an overall size of 2048 bytes.
Thoughts or help would be appreciated!
@Flexo I have seen your other SWIG posts on StackOverflow and you seem to by my guy for helping me out. Fingers crossed you see this!
Upvotes: 5
Views: 2156
Reputation: 617
I have had the same problem, and have just got it to work.
C++ as follows
// Access.h
class Access
{
void foo(unsigned char *inputBytes, int nbytes);
};
Swig .i file is then as follows. It appears to be important that the %apply appears before the %include of the code to be wrapped. If it is after then nothing changes.
%include "arrays_csharp.i"
%apply unsigned char INPUT[] {unsigned char *inputBytes}
%include "Access.h"
C# is then like this
byte[] data = ...
var access = new Access();
access.foo(fileBytes, fileBytes.Length);
With swig 3.0.2 I could not get this to work at all. With swig 3.0.12 I was successful.
I have not yet needed an output array, but this method would at least work with a pre-allocated buffer in C#.
Upvotes: 4