MATLAB input struct with unsigned char into MEX file - matlab

I tried to input this struct from MATLAB into my MEX file: struct('speed',{100.3},'nr',{55.4},'on',{54}), but the last value which is defined in my MEX file as unsigned char reads out as zero before calling my C function? The two double values works like intended.
struct post_TAG
{
double speed;
double nr;
unsigned char on;
};
const char *keys[] = { "speed", "nr", "on" };
void testmex(post_TAG *post)
{
...
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[])
{
post_TAG post;
int numFields, i;
const char *fnames[3];
mxArray *tmp;
double *a,*b;
unsigned char *c;
numFields=mxGetNumberOfFields(prhs[0]);
for(i=0;i<numFields;i++)
fnames[i] = mxGetFieldNameByNumber(prhs[0],i);
tmp = mxGetField(prhs[0],0,fnames[0]);
a=(double*)mxGetData(tmp);
tmp = mxGetField(prhs[0],0,fnames[1]);
b=(double*)mxGetData(tmp);
tmp = mxGetField(prhs[0],0,fnames[2]);
c=(unsigned char*)mxGetData(tmp);
mexPrintf("POST0, speed=%f, nr=%f, on=%u\n",*a,*b,*c);
post.speed = *a;
post.nr = *b;
post.on = *c;
testmex(&post);
}

In a struct defined as struct('speed',{100.3},'nr',{55.4},'on',{54}), the field on is a double. Pass as a uint8 from MATLAB:
struct('speed',{100.3},'nr',{55.4},...
'on',{uint8(54)}),
Any numeric value without a specified type in MATLAB is a double.
Also note that for reading a scalar value, the problem is simplified somewhat by mxGetScalar. It will return one double value for any underlying data type.
unsigned char s = (unsigned char) mxGetScalar(...); // cast a double to unsigned char

Related

error using cublasSgemmBatched in mex

I am trying to multiply Multiple Matrices from within matlab using cublasSgemmBatched in a mex file.
My matlab code is very simple:
gpuDevice(1);
a = single(rand(400,10,1500,'gpuArray'));
b = single(rand(10,12,1500,'gpuArray'));
c = MatCuda(a,b)
I get the following error:
Error using gpuArray/subsref
An unexpected error occurred during CUDA execution. The CUDA error was:
unknown error
and here's the mexFunction code:
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]){
char const * const errId = "parallel:gpu:mexGPUExample:InvalidInput";
char const * const errMsg = "Invalid input to MEX file.";
/* Declare all variables.*/
mxGPUArray const *A;
mxGPUArray const *B;
mxGPUArray *C;
/* Initialize the MathWorks GPU API. */
mxInitGPU();
/* Throw an error if the input is not a GPU array. */
if ((nrhs != 2) || !(mxIsGPUArray(prhs[0])) || !(mxIsGPUArray(prhs[1]))) {
mexErrMsgIdAndTxt(errId, errMsg);
}
A = mxGPUCreateFromMxArray(prhs[0]);
B = mxGPUCreateFromMxArray(prhs[1]);
if ((mxGPUGetClassID(A) != mxSINGLE_CLASS) || (mxGPUGetClassID(B) != mxSINGLE_CLASS)) {
mexErrMsgIdAndTxt(errId, errMsg);
}
float const *d_A;
float const *d_B;
d_A = (float const *)(mxGPUGetDataReadOnly(A));
d_B = (float const *)(mxGPUGetDataReadOnly(B));
const mwSize *dimsA = mxGPUGetDimensions(A);
size_t nrowsA = dimsA[0];
size_t ncolsA = dimsA[1];
size_t nMatricesA = dimsA[2];
mxFree((void*) dimsA);
const mwSize *dimsB = mxGPUGetDimensions(B);
size_t nrowsB = dimsB[0];
size_t ncolsB = dimsB[1];
size_t nMatricesB = dimsB[2];
mxFree((void*)dimsB);
size_t nrowsC = nrowsA;
size_t ncolsC = ncolsB;
mwSize dimsC[3] = { nrowsA, ncolsB, nMatricesB };
C = mxGPUCreateGPUArray(mxGPUGetNumberOfDimensions(A),
dimsC,
mxGPUGetClassID(A),
mxGPUGetComplexity(A),
MX_GPU_DO_NOT_INITIALIZE);
float *d_C;
d_C = (float *)(mxGPUGetData(C));
cublasHandle_t handle;
cublasStatus_t ret;
ret = cublasCreate(&handle);
if (ret != CUBLAS_STATUS_SUCCESS)
{
printf("cublasCreate returned error code %d, line(%d)\n", ret, __LINE__);
exit(EXIT_FAILURE);
}
const float alpha = 1.0f;
const float beta = 0.0f;
ret = cublasSgemmBatched(handle, CUBLAS_OP_N, CUBLAS_OP_N, nrowsA, ncolsB, ncolsA, &alpha, &d_A, nrowsA, &d_B, nrowsB, &beta, &d_C, nrowsC, nMatricesA);
if (ret != CUBLAS_STATUS_SUCCESS)
{
printf("cublasSgemm returned error code %d, line(%d)\n", ret, __LINE__);
exit(EXIT_FAILURE);
}
ret = cublasDestroy(handle);
if (ret != CUBLAS_STATUS_SUCCESS)
{
printf("cublasCreate returned error code %d, line(%d)\n", ret, __LINE__);
exit(EXIT_FAILURE);
}
plhs[0] = mxGPUCreateMxArrayOnGPU(C);
mxGPUDestroyGPUArray(A);
mxGPUDestroyGPUArray(B);
mxGPUDestroyGPUArray(C);
}
I suspect it's related to the function cublasSgemmBatched because when I remove it from the code then I don't get the error.
Help will be very much appreciated !
Thanks !
You don't need a MEX file here, you can use pagefun to do this. Also, I'd recommend building a and b in single precision directly rather than casting. In other words,
a = rand(400,10,1500,'single','gpuArray');
b = rand(10,12,1500,'single','gpuArray');
c = pagefun(#mtimes, a, b);
cublasDgemm works for me. I just pass regular arrays to the mexfunction. Here is my example code.
#include <cuda_runtime.h>
#include <cublas_v2.h>
#include <time.h>
#include "mex.h"
#include "mxGPUArray.h"
typedef struct _matrixSize
{
unsigned int uiWA, uiHA, uiWB, uiHB, uiWC, uiHC;
} sMatrixSize;
void matrixMultiply(double const* d_A, double const* d_B, double* d_C, sMatrixSize &matrix_size);
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, mxArray const *prhs[])
{
mxGPUArray const *A;
mxGPUArray const *B;
mxGPUArray *C;
_matrixSize matrix_size;
mwSize const *A_sz;
mwSize const *B_sz;
double const *d_A;
double const *d_B;
double *d_C;
char const * const errId = "parallel:gpu:mexGPUExample:InvalidInput";
char const * const errMsg = "Invalid input to MEX file.";
if (nrhs != 2) {
mexErrMsgTxt("Need two inputs");
}
A = mxGPUCreateFromMxArray(prhs[0]);
B = mxGPUCreateFromMxArray(prhs[1]);
A_sz=mxGPUGetDimensions(A);
B_sz = mxGPUGetDimensions(B);
matrix_size.uiWA = (unsigned int)A_sz[0]; matrix_size.uiHA = (unsigned int)A_sz[1];
matrix_size.uiWB = (unsigned int)B_sz[0]; matrix_size.uiHB = (unsigned int)B_sz[1];
mwSize C_sz[3] = { matrix_size.uiWA, matrix_size.uiHB, 1 };
d_A = (double const *)(mxGPUGetDataReadOnly(A));
d_B = (double const *)(mxGPUGetDataReadOnly(B));
C = mxGPUCreateGPUArray(mxGPUGetNumberOfDimensions(A),
C_sz,
mxGPUGetClassID(A),
mxGPUGetComplexity(A),
MX_GPU_DO_NOT_INITIALIZE);
d_C = (double *)(mxGPUGetData(C));
matrixMultiply(d_A, d_B, d_C, matrix_size);
plhs[0] = mxGPUCreateMxArrayOnGPU(C);
mxFree((void*)A_sz);
mxFree((void*)B_sz);
mxGPUDestroyGPUArray(A);
mxGPUDestroyGPUArray(B);
mxGPUDestroyGPUArray(C);
}
void matrixMultiply(double const* d_A, double const* d_B, double* d_C, sMatrixSize &matrix_size)
{
cublasStatus_t status;
cublasHandle_t handle;
status=cublasCreate(&handle);
if (status != CUBLAS_STATUS_SUCCESS)
{
if (status == CUBLAS_STATUS_NOT_INITIALIZED) {
mexPrintf("CUBLAS initializing error");
}
getchar();
return;
}
const double alpha = 1.0f;
const double beta = 0.0f;
cublasDgemm(handle, CUBLAS_OP_N, CUBLAS_OP_N, matrix_size.uiWB, matrix_size.uiHA, matrix_size.uiWA, &alpha, d_B, matrix_size.uiWB, d_A, matrix_size.uiWA, &beta, d_C, matrix_size.uiWB);
cudaThreadSynchronize();
cublasDestroy(handle);
}
There is also a more native cuda style. Both works fine for me.
#include <cuda_runtime.h>
#include <cublas_v2.h>
#include <time.h>
#include "mex.h"
#include "mxGPUArray.h"
typedef struct _matrixSize
{
unsigned int uiWA, uiHA, uiWB, uiHB, uiWC, uiHC;
} sMatrixSize;
void matrixMultiply(double const* d_A, double const* d_B, double* d_C, sMatrixSize &matrix_size);
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, mxArray const *prhs[])
{
mxArray const *mA;
mxArray const *mB;
_matrixSize matrix_size;
size_t A_w, A_h, B_w, B_h;
double *d_A;
double *d_B;
double *d_C;
double *h_A;
double *h_B;
double *h_C;
char const * const errId = "parallel:gpu:mexGPUExample:InvalidInput";
char const * const errMsg = "Invalid input to MEX file.";
if (nrhs != 2) {
mexErrMsgTxt("Need two inputs");
}
mA = prhs[0]; mB = prhs[1];
A_w = mxGetM(mA);A_h = mxGetN(mA);B_w = mxGetM(mB);B_h = mxGetN(mB);
matrix_size.uiWA = (unsigned int)A_w; matrix_size.uiHA = (unsigned int)A_h;
matrix_size.uiWB = (unsigned int)B_w; matrix_size.uiHB = (unsigned int)B_h;
matrix_size.uiWC = (unsigned int)A_w; matrix_size.uiHC = (unsigned int)B_h;
mwSize const C_sz[3] = { matrix_size.uiWA, matrix_size.uiHB, 1 };
unsigned int size_A = matrix_size.uiWA * matrix_size.uiHA;
unsigned int mem_size_A = sizeof(double) * size_A;
h_A = (double*)mxGetData(mA);
unsigned int size_B = matrix_size.uiWB * matrix_size.uiHB;
unsigned int mem_size_B = sizeof(double) * size_B;
h_B = (double*)mxGetData(mB);
unsigned int size_C = matrix_size.uiWC * matrix_size.uiHC;
unsigned int mem_size_C = sizeof(double) * size_C;
plhs[0] = mxCreateNumericArray(3, C_sz, mxDOUBLE_CLASS, mxREAL);
h_C = (double*)mxGetData(plhs[0]);
cudaMalloc((void **)&d_A, mem_size_A);
cudaMalloc((void **)&d_B, mem_size_B);
cudaMemcpy(d_A, h_A, mem_size_A, cudaMemcpyHostToDevice);
cudaMemcpy(d_B, h_B, mem_size_B, cudaMemcpyHostToDevice);
cudaMalloc((void **)&d_C, mem_size_C);
matrixMultiply(d_A, d_B, d_C, matrix_size);
cudaMemcpy(h_C, d_C, mem_size_C, cudaMemcpyDeviceToHost);
cudaThreadSynchronize();
cudaFree(d_A);
cudaFree(d_B);
cudaFree(d_C);
}
void matrixMultiply(double const* d_A, double const* d_B, double* d_C, sMatrixSize &matrix_size)
{
cublasHandle_t handle;
cublasCreate(&handle);
const double alpha = 1.0f;
const double beta = 0.0f;
cublasDgemm(handle, CUBLAS_OP_N, CUBLAS_OP_N, matrix_size.uiWB, matrix_size.uiHA, matrix_size.uiWA, &alpha, d_B, matrix_size.uiWB, d_A, matrix_size.uiWA, &beta, d_C, matrix_size.uiWB);
cublasDestroy(handle);
}

Store std::strings in mex cell array

Inspired from this post, I am interested to pass std::strings into the cell array. However, the mxDuplicateArray accepts mxArray format variables. I have tried to transform the std::string to mxArray with mxGetString but without success.
Could you please make a suggestion on this?
Thanks!
void mexFunction(int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[])
{
std::string str ("Hellooo");
const char *cstr = str.c_str();
mwSize len = 10;
mxArray *mxarr = mxCreateCellMatrix(len, 1);
mxArray *mxstr = mxCreateString("");
mxGetString(mxstr, (char*) cstr, str.length());
for(mwIndex i=0; i<len; i++) {
// I simply replaced the call to mxDuplicateArray here
mxSetCell(mxarr, i, mxDuplicateArray(mxstr));
}
mxDestroyArray(mxstr);
plhs[0] = mxarr;
}
You could also cut out the call to mxDuplicateArray (and mxDestroyArray).
#include "mex.h"
#include <string>
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
std::string str("Hellooo");
const char *cstr = str.c_str();
mwSize len = 10;
mxArray *mxarr = mxCreateCellMatrix(len, 1);
for (mwIndex i=0; i<len; i++) {
mxSetCell(mxarr, i, mxCreateString(cstr));
}
plhs[0] = mxarr;
}
Untested...
From the docs on mxGetString:
Call mxGetString to copy the character data of a string mxArray
What you want, is the opposite: create an mxArray from a c-style string. For that you can use
mxCreateString directly. It seems to tried to use it to create an empty string at first. This should work:
void mexFunction(int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[])
{
std::string str ("Hellooo");
const char *cstr = str.c_str();
mwSize len = 10;
mxArray *mxarr = mxCreateCellMatrix(len, 1);
mxArray *mxstr = mxCreateString(cstr);
// no need for this line
// mxGetString(mxstr, (char*) cstr, str.length());
for(mwIndex i=0; i<len; i++) {
// I simply replaced the call to mxDuplicateArray here
mxSetCell(mxarr, i, mxDuplicateArray(mxstr));
}
mxDestroyArray(mxstr);
plhs[0] = mxarr;
}

Returning structs inside a class

I am converting my application to an OOP type but I am having problem with helper functions. What I did was place helper functions inside the class as private. How should I declare a function "addSection" to return a struct
This is for my .cpp file
section_t XIniFile::*addSection(ini_file_t *n, char *d)
{
section_t *s = (section_t *)malloc(sizeof(section_t *);
//add sections
return s;
}
This is for my .h file
class XIniFile
{
public:
int open(const char *);
int readString(const char *, const char *, char *);
int readInt(const char *, const char *, int *);
int writeString(const char *, const char *, char *);
int writeInt(const char *, const char *, int *);
int close();
private:
typedef struct key_tag {
char *name;
char *value;
key_tag *next;
} key_tag_t;
typedef struct sections_tag {
char *name;
sections_tag *next;
key_tag_t *keys;
} section_t;
typedef struct {
char *name;
section_t *sections;
int modified;
} ini_file_t;
section_t *add_section(ini_file_t *, char *);
key_tag_t *add_key(section_t *, char *, char *);
};
There are a lot of errors but I would like to start first from the first error which is error: ‘section_t’ does not name a type
turn add_section into:
XIniFile::section_t * XIniFile::add_section(ini_file_t *n, char *d)
since section_t is a member of XIniFile
Your struct section_t and other structs need to be declared above the functions that use them, like add_section. C++ type declarations are forward visible, meaning their visibility extend from the point they are first declared onward, but not behind. Order matters, it is an inherited trait of the C language, based on "textual" treatment of include files as opposed to true modules or multi file type metadata, where the compiler traditionally notes each type as it is declared syntactically, stores it in a symbol table, where it is immediately available.
This differs from Java or C# compilers which parse the whole source file first, then resolve types and symbols later, removing order from the equation.
Another error, your * is in the wrong place, move it to directly after section_t:
section_t XIniFile::*addSection(ini_file_t *n, char *d)
Change to:
XIniFile::section_t* XIniFile::addSection(ini_file_t *n, char *d)
Also, in C++ you don't have to use typedef for structs as in C. You can simply say:
struct key_tag_t {
char *name;
char *value;
key_tag_t *next;
};
struct section_t {
char *name;
sections_tag *next;
key_tag_t *keys;
};
section_t *add_section(ini_file_t *, char *);
key_tag_t *add_key(section_t *, char *, char *);
structs and classes are implicitly "typedefed" in C++, though there is a minor difference, it isn't relevant.

Use of mexSet to access CData via a MEX file

I'm trying to plot data out from a MEX file (C language). To do this fast, I would like to use what corresponds to the following Matlab code:
figure; imagehandle = imagesc(rand(500));
new_CData = rand(500);
set(newCData,imagehandle);
For this, the command mexSet() should be working. Ideally, I want something like this
mex plotX.c
figure; imagehandle = imagesc(rand(500));
A = rand(500);
plotX(A,imagehandle)
with a mex-Function plotX. Here is my tryout:
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *x, imagehandle;
(void) plhs;
x = mxGetPr(prhs[0]);
imagehandle = mxGetScalar(prhs[1]);
mexSet(imagehandle,"Cdata",x);
}
This can be compiled, but I get the following error: "Error using plotX. Numeric or logical matrix required for image CData".
What am I doing wrong?
Solution:
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *x, imagehandle;
(void) plhs;
imagehandle = mxGetScalar(prhs[1]);
mexSet(imagehandle,"Cdata",prhs[0]);
}
I found this out when I used a different compiler which gave me the following error: " note: expected ‘struct mxArray *’ but argument is of type ‘double *’". And prhs[] is already a mxArray, so easy to solve ...

Array of int at the output of a mex file

I am trying to create a mex function whose entry is an integer and whose output is an array of integer.
So the function looks like: int *myFunction(unsigned int N).
In the mexFunction, I declare a variable *variab of type int and then
N = mxGetScalar(prhs[0]);
/* assign a pointer to the output */
siz= 2*ceil(log(1.0*N)/log(2.0)-0.5)+1;
plhs[0] = mxCreateDoubleMatrix(1,siz, mxREAL);
vari = (int*) mxGetPr(plhs[0]); */
/* Call the subroutine. */
vari = myFunction(N);
mexPrintf("The first value is %d\n", vari[0]);
The thing is the first value is the correct one (and the other ones were checked and were correct as well) but when I call the routine mxFunction(16), I get only 0's as output.
I guess it is because my output is an array of int but I don't know how to solve the problem. Any hint?
Cheers.
Matlab deals with doubles by default. You can easily cast them in your mex function like the following example based on your code snippet. I have made a myFunction that performs a demo algorithm. Rather than return a data type, I make it a void function and pass it a pointer to the output so that it can populate it . . .
/*************************************************************************/
/* Header(s) */
/*************************************************************************/
#include "mex.h"
#include "math.h"
/*************************************************************************/
/*the fabled myFunction */
/*************************************************************************/
void myFunction(unsigned int N, unsigned int siz, double* output)
{
int sign = 1;
for(int ii=0; ii<siz; ++ii)
{
output[ii] = (double)(ii * sign + N);
sign *= -1;
}
}
/*************************************************************************/
/* Gateway function and error checking */
/*************************************************************************/
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
/* variable declarations */
unsigned int siz;
double N;
/* check the number of input and output parameters */
if(nrhs!=1)
mexErrMsgTxt("One input arg expected");
if(nlhs > 1)
mexErrMsgTxt("Too many outputs");
N = mxGetScalar(prhs[0]);
/* assign a pointer to the output */
siz= 2*ceil(log(1.0*N)/log(2.0)-0.5)+1;
plhs[0] = mxCreateDoubleMatrix(1,siz, mxREAL);
myFunction(N, siz, mxGetPr( plhs[0]) );
}