Passing a Pointer Representing a 2D Array to a Function in C++

Passing a pointer representing a 2D array to a function in C++

Regarding the edit: to pass this double stuff[3][3] to a C function, you could

1) pass a pointer to the whole 2D array:

void dostuff(double (*a)[3][3])
{
// access them as (*a)[0][0] .. (*a)[2][2]
}
int main()
{
double stuff[3][3];
double (*p_stuff)[3][3] = &stuff;
dostuff(p_stuff);
}

2) pass a pointer to the first 1D array (first row) and the number of rows

void dostuff(double a[][3], int rows)
{
// access them as a[0][0] .. a[2][2]
}
int main()
{
double stuff[3][3];
double (*p_stuff)[3] = stuff;
dostuff(p_stuff, 3);
}

3) pass a pointer to the first value in the first row and the number of both columns and rows

void dostuff(double a[], int rows, int cols)
{
// access them as a[0] .. a[8];
}
int main()
{
double stuff[3][3];
double *p_stuff = stuff[0];
dostuff(p_stuff, 3, 3);
}

(that this last option is not strictly standards-compliant since it advances a pointer to an element of a 1D array (the first row) past the end of that array)

If that wasn't a C function, there'd be a few more options!

How to pass a 2D array by pointer in C?

char ** doesn't represent a 2D array - it would be an array of pointers to pointers. You need to change the definition of printarray if you want to pass it a 2D array:

void printarray( char (*array)[50], int SIZE )

or equivalently:

void printarray( char array[][50], int SIZE )

Passing 2-D arrays with pointers

There is a subtle difference:

char (*twoDArr[4])

int (*arr) [M]

(The parentheses)

The first pair does nothing - twoDArr is an array of 4 pointers to char.

The second example makes arr first a pointer - one to an array of M ints.
Since M is a variable (even with const...), this is a fixed-size VLA. This way it would make more sense:

void print(int M, int (*arr)[M])

Now it can handle different dimensions, if the caller gives that value.

if I swap out a bracket for a star,

The first, empty bracket can be replaced, but not the crucial other dimensions.

The other strategy is an array of pointers. I am not even sure if the terminolgy is 100% clear with "2D array". That is where you'd get a char ** type; the first dim. moves by a pointer (to a row), not by a given number of elements directly.

Calling a C function from Julia and passing a 2D array as a pointer of pointers as argument

I will try to answer you questions one by one:

Is there any other way to pass a 2-dimensional matrix to a C function that expects an argument of the type int **arg?

Yes. You have to add a method to julia's cconvert function so that it does the conversion from Matrix{Cint} to Ptr{Ptr{Cint}}. So you define:

Base.cconvert(::Type{Ptr{Ptr{Cint}}},xx2::Matrix{Cint})=Ref{Ptr{Cint}}([Ref(xx2,i) for i=1:size(xx2,1):length(xx2)])

(see next question for explanation) and can afterwards directly pass your matrix to ccall:

xx2=zeros(Cint,5,6)
ccall((:fill_matrix, "mylib.so"),Void, (Ptr{Ptr{Cint}}, Cint, Cint), xx2, 6,5)

However, I would suggest to be very conservative in which cconvert methods you overwrite, because other julia code might expect the original behavior.

If not, how can you transform an already existing 2-dimensional array of Julia to the array of arrays structure of C?

The following should work: You generate an Array of pointers to every column of your matrix, so in julia-0.4:

xx2=zeros(Cint,5,6)
refAr=[Ref(xx2,i) for i=1:size(xx2,1):length(xx2)]
ccall((:fill_matrix, "mylib.so"),Void, (Ptr{Ptr{Cint}}, Cint, Cint), refAr, 6,5)

Now the matrix xx2 is filled by the C function. Note that in julia v0.3 you have to replace Ref(xx2,i) with pointer(xx2,i)

and the other way around?

I don't think this is generally possible. In order to construct a julia 2D array, the data must be in a contiguous block of memory. If you are REALLY confident this is the case you can do:

p=pointer(refAr)  # This is a Ptr{Ptr{Cint}} representing the int**
aa=pointer_to_array(p,6,false)
bb=pointer_to_array(aa[1],(5,6),false)

Which returns the original matrix. Here, the last argument to pointer_to_array determines, if Julia takes the ownership of the array and the data should be freed by Julia's gc.



Related Topics



Leave a reply



Submit