C within C++ code - c++

I have written a C++ application and within it, I need to call a math function that was written in C. The prototype looks like:
void Jacobi_Cyclic_Method(double *eigenvalues, double *eigenvectors, double *A, int n);
My problem is that I can't seem to pass the function double * (for instance both eigenvectors and A are multi-dimensional arrays. The C++ way to pass those things seems to be
double [][size]
I have read about extern C but I don't think it applies here since I am not interfacing with an object but with source itself. How can I send that C function my multi-dimensional arrays defined as such:
double [100][100] A;
double [100][100] eigenvectors;
double [100] eigenvalues;
Trying to compile I get:
error: no matching function for call to ‘MathEngine::Jacobi_Cyclic_Method(double
[100], double [100][100], double [100][100], int)’
mathEngine.h:9: note: candidates are: static void
MathEngine::Jacobi_Cyclic_Method(double*, double*, double*, int)

Probably the problem is that your Jacobi_Cyclic_Method function requires the matrix to be in either column or row major format, where every column/row is stored consecutively in a single, one-dimensional array. E.g. for a row major matrix of size m x n, the elements in any given row are stored contiguously and the item in row i and column j would be at position i*n+j (for zero-based indices i and j). If the matrix is column-major, it would be at position i+j*m.
Using multi-dimensional arrays in C/C++ is often not what you want because something like
double A[100][100];
is not a two-dimensional array, but a single array of length 100 containing pointers to arrays of length 100. Consequently, the rows in A are not stored contiguously.

I'm assuming that your C function requires multi-dimensional arrays for some of its parameters and that the prototype is written with pointers to doubles for the array/matrix parameters where the integer parameter indicates the size of each dimension (I guess the matrices are square?). If this is the case then you can pass a pointer to the first element of each array/matrix like this:
Jacobi_Cyclic_Methods(&eigenvalues[0], &eigenvectors[0][0], &A[0][0], 100);
Your initial attempt doesn't work because the type of, for instance, eigenvectors is double[100][100] which decays to double (*)[100], not double *.
This post addresses the issue of pointers and multi-dimensional arrays.

Related

How to convert one-dimensional array into two-dimensional without memory allocating?

I have a filled one-dimensional array double *vals as a class component with sizes Nn[0]*Nn[1]. I need to get 2-dimensional array **w (w[Nn[1]][Nn[0]]) without allocating new memory for it, e.g. i need to represent vals as 2-dimensional array.
Using g++ compiler i can make
double (* w)[Nn[0]] = (double (*)[Nn[0]])val;
But VS compiler or intel compiler don't allow to use non-constant expression as dimension array.
In general, I can just use element in initial vals array converting 2 int indices (i,j) of w[i][j] element into global index and do not declare w at all. But it would be great if it's possible to get 2-dimensional array w on initial memory (with compiling with intel compiler too). So is there any way to do it?
If wals is a class, you can implement your access operator to function as if it were 2D array.
walsdataType walsclass::operator()(int i, int j){return walsdata[i*N+j]};
with walsdata being the class member for storing data and N being the row length. You should do the bound checking as well.

Calling C++ function in Matlab, deal with 2-dimensional array, pointer of pointer?

I am trying to call a function in C++ in Matlab, I thought I have written my functions properly. The function I want to call, looks like this, it has 8 arguments as input.
void LimitedPrice(double &dMarketPosition, double** dmatLimitPrice,
char* FileID, double* dvecOpen, double* dvecClose,
double** dmatTempData, int tick, double dMaxBarBack)
{Bla, Bla, Bla}
I want to get 2 values after running this function. Which stored in dMarketPosition, and dmatLimitPrice since they are pointers.
In this function, I have to use some ** (double pointers) to represent my Matrix.
After running this function, dMarketPosition, dmatLimitPrice will store what I want, since they are pointers. I have tested my function and I believed my function are written properly.
Now I am ready to write my mexFunction().
My mex function somehow looks like this
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs,const mxArray *prhs[])
{
if(nrhs!=8){
mexErrMsgIdAndTxt("LimitPrice: ","I want to 8 inputs");
}
// I want two output
if(nlhs!=2) {
mexErrMsgIdAndTxt("LimitPrice: ","I want to 2 outputs");
}
//The first input is a scalar
double dmarketposition;
dmarketposition = mxGetScalar(prhs[0]);
//The second input is a 2-dimensional Matrix
double **dmatlimitprice;
*dmatlimitprice = mxGetPr(prhs[1]);
/*****Assuming I have checked other inputs here properly*****/
// I want to define my outputs
// Create 1*1 matrix as output, which is the double value I want
plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);
//The second output is a two dimensional matrix
plhs[1] = mxCreateDoubleMatrix(2,(mwSize)4,mxREAL);
dmarketposition = mxGetScalar(plhs[0]);
*dmatlimitprice = mxGetPr(plhs[0]);
// Call the function
LimitedPrice(dmarketposition, dmatlimitprice, fileid,
dvecopen, dvecclose, dmattempdata, tick, dmaxbarback);
}
The above function does not seem to work... It seems that in mexFunction(),
We would better only pass one-dimensional array, which is double *a like thing.
My key issue is "How can we deal with 2-dimensional array, which is a matrix" in mexFunction().
In memory, Matlab stores all mxArrays as one chunk of contiguous memory column by column. In that respect, there is no difference beteween a 1D vector and N-D array, they are all stored as a single chunk of memory.
Consider, for example, the following chunk in memory: { 1, 2, 3, 4, 5, 6, 7, 8 }
It can be treated as a 1-by-8, 8-by-1, 2-by-4, 4-by-2 or even 2-by-2-by-2 array. Changing the shape (reshape-ing) of the array does not require any change to the actual memory where the data is stored, only to the "header" of the mxArray.
What you can do is allocate a 2D matrix internally, call LimitedPrice and then copy the result into the output mxArray converting it from the internal double** representation to double* mxArray representation.
A side note, in your example code you assign dmarketposition and dmatlimitprice twice: once from the first and second inputs and once from the newly allocated outputs - the second assignment simply overrides the first and it seems like your function LimitedPrice will not get the information stored in the mexFunction inputs.
The only thing that makes an array 2D (or any size other than 1D) is the shape of the array as stored in the mxArray structure. All the data is contiguous. The stride, or step in bytes between columns, of a 2D array in MATLAB (and mxArrays) is always number_of_rows * element_size. For a column-major storage system, that's a way of saying that a contiguous data buffer is used to store all arrays.
Take the basic functions for reading from a mxArray:
double* mxGetPr(const mxArray*); // get pointer to start of double buffer
void* mxGetData(const mxArray*); // get pointer to start of any data-type buffer
size_t mxGetM(const mxArray*); // get number of rows
size_t mxGetN(const mxArray*); // get number of columns
There is no function like OpenCV's T* ptr<T>(int i) to get a pointer to specified row (or column in MATLAB's case). To get an element, you just have to access location irow + icol*numRows. This is why it is common to have a sub2ind-like function in C/C++:
inline mwSize sub2ind(mwSize irow, mwSize icol, mwSize numRows) {
return irow + icol*numRows; }
That was generic advice, nothing specific to your code. I'm hesitant to to make specific suggestions since semantics of LimitedPrice() is not clear. The syntax is clear -- it needs a pointer to a pointer -- but often a ** is used to return a new pointer (internally allocated result) rather than to manage a 2D array. If it's 2D data then usually there will be two integral types with it to specify dimensions, but I don't see that.
For the reasons above it's hard to provide more specific help, but here here is a big issue to address:
double **dmatlimitprice;
*dmatlimitprice = mxGetPr(prhs[1]); // dereferencing uninitialized pointer, ERROR
You could make a double** that acts as an index into the columns of the input matrix (if that is what you actually need!). For example:
size_t numCols = mxGetN(prhs[1]);
double *dlimitBuffer = mxGetPr(prhs[1]);
// Simulate a 2D array:
std::vector<double*> dlimitvec(numCols);
double **dmatlimitprice = &dlimitvec[0]; // or = new double*[numCols]; if you delete[]
for (size_t i=0; i < numCols; ++i)
datalimitprice[i] = dlimitBuffer + i*numRows;
That's assuming you need a double** where each double* points to the individual columns of some matrix, which is likely not correct, so treat this as an example. You may need to transpose the matrix too.
Also, you make the invalid assignment to *dmatlimitprice twice so it's hard to tell whether you want this as the input or output array.

how to code multi-dimensional array in a function prototype in c++

When I create a multidimensional array like value[][],and pass it to the function.But I am quite confused about how to write a prototype for this function,because there is an error message like:
error: declaration of 'value' as multidimensional array must have bounds for all dimensions except the first|
//function prototype;
void matrix(double s[],int j,int n,double value[][],double alpha[], double beta[], double gamma[]);
//function
void matrix(double s[],int j,int n,double value[][],double alpha[], double beta[],double gamma[]){...}
help,How to write it correctly?
The error message from the compiler is very telling. The argument double value[][] needs to be changed to double vale[][N] where N is a integer. Examples:
double value[][20] // A matrix in which each row has 20 columns.
double value[][10] // A matrix in which each row has 10 columns.
the compiler already told you
error: declaration of 'value' as multidimensional array must have bounds for all dimensions except the first|
you need specify the length, eg: double s[3], double[3][3] etc.
The folks above have given the technical explanation.
The reason behind is is that C and C++ treat arrays as blocks of memory. When an array gets passed to a function, all that gets sent is a pointer to the array. This is in stark contrast to Ada, Pascal, and Fortran that send descriptors of the array to the function.
Your declaration must provide enough information to work with the array with just a pointer passed. That means is need all but the last (first specified) array dimension.
Multidimensional arrays of variable size are usually a sign of bad design. If you have a fixed array size (4x4 is common in 3D transforms), 2D array work out well. For something like general purpose matrix operations, 2D arrays do not work well.
For that you need to define a class that:
1) Manages a 1D array
2) Provides the mechanism for translating 2D references into 1D index.
What you would do is something like
class Matrix
{
unsigned int range1 ;
unsigned int range2
double *values ; // Could use a template
double &valueAt (unsigned int x, unsigned int y) { return values [range1 * x + y] ; }
} ;

Passing a 3-dimensional variable size array by reference in C++

I've been working off of Passing a 2D array to a C++ function , as well as a few other similar articles. However, I'm running into a problem wherein the array I'm creating has two dimensions of variable size.
The initialization looks like:
int** mulePosition;
mulePosition = new int *[boardSize][boardSize][2];
The function looks like:
int moveMule (int boardSize, int ***mulePosition)
And the references look like
moveMule (boardSize, mulePosition)
Boardsize is defined at the beginning of the function, but may change per execution.
The array, properly sized, would be int [boardSize][boardSize][2].
Either use a plain '3-dimensional' array via
int* mulePosition = new int[boardsize*boardsize*2];
and address its elements calculating the offset from the beginning: mulePosition[a][b][c] is mulePosition[boardSize*2*a + 2*b + c],
or use array of arrays of arrays (which would correspond to your int*** declaration) or better (and simpler) vector of vectors of vectors, although the initialization would be a little more complex (you would need to initialize every array/vector).
Either use a std::vector<std::vector<int>> if boardSize is not a const or std::array<std::array<boardSize>, boardSize> (see Multidimensional std::array for how to initialize the std::array).
That being said, it looks like a good idea to hide this in a class Board which provides a nice interface.

pass a 2D array from a C++ class to a CUDA function

I am a Java guy jumping into CUDA and the syntax is tripping me. I'm trying to create a matrix in the .cpp file then pass that off to the .cu file to be processed. I see examples where the CUDA function expects the 2D array to come in looking like
void handleMatrix(float* A){
// do stuff
}
when I create the matrix I'm used to doing it in code that looks like this:
int main()
{
const int row=8;
const int column=8;
int rnum;
srand(time(0));
rnum = (rand() % 100) + 1;
float table[row][column];
for(int r=0; r<row; r++){
for(int c=0; c<column;c++){
table[row][column] = (rand()%100) + 1.f;
}
cout << "\n";
}
handleMatrix(table);
return 0;
}
When I compile the code I'm getting the error
cannot convert ‘float ()[8]’ to ‘float*’ for argument ‘1’ to ‘void handleMatrix(float*)’*
Is there a different way I should be declaring the matrix or creating it?
Thanks in advance for the help.
You can do
handleMatrix(table[0]);
or, equivalently,
handleMatrix(&table[0][0]);
That's if 'handleMatrix' is host code. If it's device code, you can't allocate the buffer like that. You'll want to assemble an array in local memory, fill the entries, allocate another array in the device memory using cudaMalloc() or cudaMallocPitch(), and then copy from local to device using cudaMemcpy() or cudaMemcpy2D().
You want a pointer to an array. The syntax for declaring a pointer to an array is
void handleMatrix(float (*A)[8][8]) {
// do stuff
}
That is, when you dereference A, you get a reference to an 8 by 8 array of floats.
Even for 1D arrays, there is a distinction between pointer to array (float (*anArray)[100]) and pointer to element (float *anArray). C++ will transparently convert the former to the latter, which means that for 1D arrays (but not arrays of higher dimension) you can usually ignore the difference.
In your example, table[0] converts to a valid float* pointer to 64 consecutive float numbers. But it looks highly suspicious that handleMatrix takes a pointer meant to be an array and doesn't take any information about the dimensions of that array.
the handleMatrix() function, is this a function from you or is part of a library? If the latter you may need to create the 2-d array as a long row x col 1-d array. If the former you need to change the function to accept a 2-d array e.g. handleMatrix(float**m) and pass the dimensions of the matrix to the function;
preferably though you should use vector<> when programming in C++ then the dimensions are known by the callee.
e.g.
#include <vector>
typedef std::vector<std::vector<float > > matrix;
void handleMatrix( matrix& m ) {..}