I'm looking for a way to pass an array from C# to C/C++ code without additional data copy. At the first glance using built-in SWIG typemap for C# is a way to go. But there is a couple of things that bugging me.
First thing: I want to use C# spans, because my data is not always represented by C# array.
Second thing: I want to pass span or array length to C/C++ code automatically. I.e. I want to wrap this two-argument C function:
// Calculator.hpp
long long CalculateSum(int* numbers, int count);
Into this single-argument C# method:
// Calculator.cs
public static long CalculateSum(Span<int> numbers)
{
// ...
}
This is what I managed to do so far:
// Calculator.i
%module Calculator
%{
#include "Calculator.hpp"
%}
// A macro based on `CSHARP_ARRAYS_FIXED` from `arrays_csharp.i`:
%define CSHARP_FIXED_SPAN( CTYPE, CSTYPE )
%typemap(ctype) CTYPE FIXED_SPAN "CTYPE*"
%typemap(imtype) CTYPE FIXED_SPAN "global::System.IntPtr"
%typemap(cstype) CTYPE FIXED_SPAN "global::System.Span<CSTYPE>"
%typemap(csin,
pre= " fixed ( CSTYPE* swig_ptrTo_$csinput = $csinput ) {",
terminator=" }")
CTYPE FIXED_SPAN "(global::System.IntPtr)swig_ptrTo_$csinput"
%typemap(in) CTYPE FIXED_SPAN "$1 = $input;"
%typemap(freearg) CTYPE FIXED_SPAN ""
%typemap(argout) CTYPE FIXED_SPAN ""
%enddef // CSHARP_FIXED_SPAN
// Instantiate fixed span typemap from the macro only for int/int types:
CSHARP_FIXED_SPAN(int, int)
// Apply the typemap to the `CalculateSum` method signature:
%apply int FIXED_SPAN {int *numbers}
// Apply `unsafe` modifier to generated C# method:
%csmethodmodifiers CalculateSum "public unsafe";
%include "Calculator.hpp"
It solves the first thing (I'm able to use spans now). But it does not solve the second thing, because the count argument still gets into generated C# code:
// Calculator.cs (generated)
public unsafe static long CalculateSum(global::System.Span<int> numbers, int count) {
fixed ( int* swig_ptrTo_numbers = numbers ) {
{
long ret = CalculatorPINVOKE.CalculateSum((global::System.IntPtr)swig_ptrTo_numbers, count);
return ret;
}
}
}
How do I get rid of the count argument in the generated wrapper mehtod? I.e. how to make SWIG generate C# wrapper code which will pass numbers.Length to C/C++ code?