Reputation: 31
I'm trying to generate a python wrapper for my C code with swig4. As I do not have any experience I'm having some issues converting a numpy-array to a c array and returning a numpy-array from a c array.
Here is my repository with all my code: https://github.com/FelixWeichselgartner/SimpleDFT
void dft(int *x, float complex *X, int N) {
X = malloc(N * sizeof(float complex));
float complex wExponent = -2 * I * pi / N;
float complex temp;
for (int l = 0; l < N; l++) {
temp = 0 + 0 * I;
for (int k = 0; k < N; k++) {
temp = x[k] * cexp(wExponent * k * l) + temp;
}
X[l] = temp/N;
}
}
This is what my C function looks like. int *x is a pointer to a integer array with the length N. float complex *X will be allocated by the function dft with the length of N.
/* File: dft.i */
%module dft
%{
#define SWIG_FILE_WITH_INIT
#include "dft.h"
%}
%include "numpy.i"
%init %{
import_array();
%}
%apply (int * IN_ARRAY1, int DIM1) {(int *x, int N)}
%apply (float complex * ARGOUT_ARRAY1, int DIM1) {(float complex *X, int N)}
%include "dft.h"
This is what my swig file looks like. I guess the %apply part in the end is false, but I have no idea how to match this.
When I build my project by executing my build.sh file the created wrapper looks like this:
def dft(x, X, N):
return _dft.dft(x, X, N)
Here I can see that swig did not recognize my %apply as I want it to look like this
def dft(x):
# N is len(x)
# do some stuff
return X # X is a numpy.array() with len(X) == len(x)
I want to use it like this:
X = dft(x)
Obviously I get this error by executing:
File "example.py", line 12, in <module>
X = dft(x)
TypeError: dft() missing 2 required positional arguments: 'X' and 'N'
Do I have to write my own typemap or is it possible for me to use numpy.i. And how would a typemap with an IN_ARRAY1 and ARGOUT_ARRAY1 in one function work.
Thanks for your help.
Upvotes: 1
Views: 344
Reputation: 36
I was working on something similar and saw that this post had no answer. Then I realized that @schnauzbartS had already solved it and his codes are on his github (linked in the question), which is a good example.
I think a simple example people might find useful if the question is about how to typemap with IN_ARRAY1 and ARGOUT_ARRAY1 is this page:
%apply (double* IN_ARRAY1 , int DIM1) {(double* vec , int m)};
%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* vec2, int n)};
Caveat: I struggled with my code a bit until I realized that IN_ARRAY from python has to be in the format of float32 not 64 (in my case it was float array). Not sure why. Another thing I found was that ARGOUT_ARRAY always needs the integer input for the size of array. So from my python end, I ended up with calling the function
myswigfunc(outarraysize,inarray,inarray2)
where outarraysize is for ARGOUT_ARRAY and the other inputs are IN_ARRAY_1 and _2 for example.
Upvotes: 1