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
Unique_Ptr and Forward Declaration
C++ Overloaded Function as Template Argument
Can Sfinae Detect Private Access Violations
Can a C++ Compiler Re-Order Elements in a Struct
Cmake Cannot Determine Linker Language for Target
Pointers to Members Representations
Math Precision Requirements of C and C++ Standard
How to Include Compiler Flags in Visual Studio Code
Base Pointer to Array of Derived Objects
How to Overwrite Only Part of a File in C++
C++11 "Overloaded Lambda" with Variadic Template and Variable Capture
Qt3D. Draw Transparent Qspheremesh Over Triangles
Why How to Call Base Template Class Method from Derived Class