UtilsLite
Utilities for C++ programming
Loading...
Searching...
No Matches
mex_utils.hxx
Go to the documentation of this file.
1
2/*--------------------------------------------------------------------------*\
3 | |
4 | Copyright (C) 2021 |
5 | |
6 | , __ , __ |
7 | /|/ \ /|/ \ |
8 | | __/ _ ,_ | __/ _ ,_ |
9 | | \|/ / | | | | \|/ / | | | |
10 | |(__/|__/ |_/ \_/|/|(__/|__/ |_/ \_/|/ |
11 | /| /| |
12 | \| \| |
13 | |
14 | Enrico Bertolazzi |
15 | Dipartimento di Ingegneria Industriale |
16 | Università degli Studi di Trento |
17 | Via Sommarive 9, I-38123 Povo, Trento, Italy |
18 | email: enrico.bertolazzi@unitn.it |
19 | |
20\*--------------------------------------------------------------------------*/
21
22#include "mex.h"
23#include <map>
24#include <string>
25#include <string_view>
26#include <cstring>
27#include <vector>
28#include <cstdint>
29#include <typeinfo>
30
31#define CLASS_HANDLE_SIGNATURE 0xFF00F0A5
32
33#define arg_in_0 prhs[0]
34#define arg_in_1 prhs[1]
35#define arg_in_2 prhs[2]
36#define arg_in_3 prhs[3]
37#define arg_in_4 prhs[4]
38#define arg_in_5 prhs[5]
39#define arg_in_6 prhs[6]
40#define arg_in_7 prhs[7]
41#define arg_in_8 prhs[8]
42#define arg_in_9 prhs[9]
43#define arg_in_10 prhs[10]
44#define arg_in_11 prhs[11]
45#define arg_in_12 prhs[12]
46#define arg_in_13 prhs[13]
47#define arg_in_14 prhs[14]
48#define arg_in_15 prhs[15]
49#define arg_in_16 prhs[16]
50#define arg_in_17 prhs[17]
51#define arg_in_18 prhs[18]
52#define arg_in_19 prhs[19]
53
54#define arg_out_0 plhs[0]
55#define arg_out_1 plhs[1]
56#define arg_out_2 plhs[2]
57#define arg_out_3 plhs[3]
58#define arg_out_4 plhs[4]
59#define arg_out_5 plhs[5]
60#define arg_out_6 plhs[6]
61#define arg_out_7 plhs[7]
62#define arg_out_8 plhs[8]
63#define arg_out_9 plhs[9]
64#define arg_out_10 plhs[10]
65#define arg_out_11 plhs[11]
66#define arg_out_12 plhs[12]
67#define arg_out_13 plhs[13]
68#define arg_out_14 plhs[14]
69#define arg_out_15 plhs[14]
70#define arg_out_16 plhs[16]
71#define arg_out_17 plhs[17]
72#define arg_out_18 plhs[18]
73#define arg_out_19 plhs[19]
74
75#define UTILS_MEX_ASSERT0( COND, MSG ) if ( !(COND) ) Utils::mex_error_message( MSG )
76
77#define UTILS_MEX_ASSERT( COND, FMT, ... ) \
78 UTILS_MEX_ASSERT0( COND, fmt::format( FMT,__VA_ARGS__) )
79
80// -----------------------------------------------------------------------------
81
82namespace Utils {
83
84 using std::string;
85 using std::string_view;
86 using std::vector;
87
92
98 inline void mex_error_message( string_view msg ) { mexErrMsgTxt( msg.data() ); }
99
107 inline
108 bool
109 mex_is_scalar( mxArray const * arg, string_view msg ) {
110 mwSize number_of_dimensions = mxGetNumberOfDimensions(arg);
111 UTILS_MEX_ASSERT0( number_of_dimensions == 2, msg );
112 mwSize const * dims = mxGetDimensions(arg);
113 return dims[0] == 1 && dims[1] == 1;
114 }
115
123 inline
124 double
125 mex_get_scalar_value( mxArray const * arg, string_view msg ) {
126 mwSize number_of_dimensions = mxGetNumberOfDimensions(arg);
127 UTILS_MEX_ASSERT0( number_of_dimensions == 2, msg );
128 mwSize const * dims = mxGetDimensions(arg);
130 dims[0] == 1 && dims[1] == 1,
131 "{}, found {} x {} matrix\n",
132 msg, dims[0], dims[1]
133 );
134 return mxGetScalar(arg);
135 }
136
144 inline
145 bool
146 mex_get_bool( mxArray const * arg, string_view msg ) {
147 UTILS_MEX_ASSERT0( mxIsLogicalScalar(arg), msg );
148 return mxIsLogicalScalarTrue(arg);
149 }
150
158 inline
159 int64_t
160 mex_get_int64( mxArray const * arg, string_view msg ) {
161 using std::floor;
162 mwSize number_of_dimensions = mxGetNumberOfDimensions(arg);
163 UTILS_MEX_ASSERT0( number_of_dimensions == 2, msg );
164 mwSize const * dims = mxGetDimensions(arg);
166 dims[0] == 1 && dims[1] == 1,
167 "{}, found {} x {} matrix\n",
168 msg, dims[0], dims[1]
169 );
170 mxClassID category = mxGetClassID(arg);
171 int64_t res = 0;
172 void *ptr = mxGetData(arg);
173 switch (category) {
174 case mxINT8_CLASS: res = *static_cast<uint8_t*>(ptr); break;
175 case mxUINT8_CLASS: res = *static_cast<uint8_t*>(ptr); break;
176 case mxINT16_CLASS: res = *static_cast<int16_t*>(ptr); break;
177 case mxUINT16_CLASS: res = *static_cast<uint16_t*>(ptr); break;
178 case mxINT32_CLASS: res = *static_cast<int32_t*>(ptr); break;
179 case mxUINT32_CLASS: res = *static_cast<uint32_t*>(ptr); break;
180 case mxINT64_CLASS: res = *static_cast<int64_t*>(ptr); break;
181 case mxUINT64_CLASS: res = *static_cast<uint64_t*>(ptr); break;
182 case mxDOUBLE_CLASS:
183 { double tmp = *static_cast<double*>(ptr);
184 UTILS_MEX_ASSERT( tmp == floor(tmp), "{} expected int, found {}\n", msg, tmp );
185 res = static_cast<int64_t>(tmp);
186 }
187 break;
188 case mxSINGLE_CLASS:
189 { float tmp = *static_cast<float*>(ptr);
190 UTILS_MEX_ASSERT( tmp == floor(tmp), "{} expected int, found {}\n", msg, tmp );
191 res = static_cast<int64_t>(tmp);
192 }
193 break;
194 default:
195 UTILS_MEX_ASSERT( false, "{} bad type scalar", msg );
196 break;
197 }
198 return res;
199 }
200
209 inline
210 double const *
212 mxArray const * arg,
213 mwSize & sz,
214 string_view msg
215 ) {
216 mwSize number_of_dimensions = mxGetNumberOfDimensions(arg);
217 UTILS_MEX_ASSERT0( number_of_dimensions == 2, msg );
218 mwSize const * dims = mxGetDimensions(arg);
220 dims[0] == 1 || dims[1] == 1 || dims[0]*dims[1] == 0,
221 "{}\nExpect (1 x n or n x 1 or empty) matrix, found {} x {}\n",
222 msg, dims[0], dims[1]
223 );
224 sz = dims[0]*dims[1];
225 return mxGetPr(arg);
226 }
227
237 inline
238 double const *
240 mxArray const * arg,
241 mwSize & nr,
242 mwSize & nc,
243 string_view msg
244 ) {
245 mwSize number_of_dimensions = mxGetNumberOfDimensions(arg);
246 UTILS_MEX_ASSERT0( number_of_dimensions == 2, msg );
247 mwSize const * dims = mxGetDimensions(arg);
248 nr = dims[0];
249 nc = dims[1];
250 return mxGetPr(arg);
251 }
252
253 // -----------------------------------------------------------------------------
254
261 inline
262 void
263 mex_set_scalar_value( mxArray * & arg, double value ) {
264 arg = mxCreateNumericMatrix(1, 1, mxDOUBLE_CLASS, mxREAL);
265 *mxGetPr(arg) = value;
266 }
267
274 inline
275 void
276 mex_set_scalar_int32( mxArray * & arg, int32_t value ) {
277 arg = mxCreateNumericMatrix(1, 1, mxINT32_CLASS, mxREAL);
278 *static_cast<int32_t*>(mxGetData(arg)) = value;
279 }
280
287 inline
288 void
289 mex_set_scalar_int64( mxArray * & arg, int64_t value ) {
290 arg = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
291 *static_cast<int64_t*>(mxGetData(arg)) = value;
292 }
293
300 inline
301 void
302 mex_set_scalar_bool( mxArray * & arg, bool value ) {
303 arg = mxCreateLogicalScalar( value );
304 }
305
318 inline
319 int32_t *
320 mex_create_matrix_int32( mxArray * & arg, mwSize nrow, mwSize ncol ) {
321 arg = mxCreateNumericMatrix( nrow, ncol, mxINT32_CLASS, mxREAL );
322 return static_cast<int32_t*>(mxGetData(arg));
323 }
324
325
338 inline
339 int64_t *
340 mex_create_matrix_int64( mxArray * & arg, mwSize nrow, mwSize ncol ) {
341 arg = mxCreateNumericMatrix( nrow, ncol, mxINT64_CLASS, mxREAL );
342 return static_cast<int64_t*>(mxGetData(arg));
343 }
344
345
358 inline
359 double *
360 mex_create_matrix_value( mxArray * & arg, mwSize nrow, mwSize ncol ) {
361 arg = mxCreateNumericMatrix( nrow, ncol, mxDOUBLE_CLASS, mxREAL );
362 return mxGetPr(arg);
363 }
364
365 // -----------------------------------------------------------------------------
383 template <typename R, typename I>
384 inline
385 int
387 size_t nnz,
388 size_t nrows,
389 size_t ncols,
390 I i_rows[],
391 I j_cols[],
392 R vals[],
393 mxArray * arg_out[]
394 ) {
395 mxArray *args[5]; // Array of arguments to be passed to MATLAB's sparse function.
396
397 // Create MATLAB matrices to store row indices, column indices, and values.
398 double *Irow = mex_create_matrix_value(args[0], 1, nnz);
399 double *Jcol = mex_create_matrix_value(args[1], 1, nnz);
400 double *VALS = mex_create_matrix_value(args[2], 1, nnz);
401
402 // Set the number of rows and columns in the sparse matrix.
403 mex_set_scalar_value(args[3], nrows);
404 mex_set_scalar_value(args[4], ncols);
405
406 // Convert the row and column indices to 1-based indexing for MATLAB.
407 std::transform(i_rows, i_rows + nnz, Irow, [](I val) -> double { return double(val + 1); });
408 std::transform(j_cols, j_cols + nnz, Jcol, [](I val) -> double { return double(val + 1); });
409
410 // Copy the values of the non-zero elements into the MATLAB array.
411 std::copy_n(vals, nnz, VALS);
412
413 // Call the MATLAB function 'sparse' to create the sparse matrix.
414 return mexCallMATLAB(1, arg_out, 5, args, "sparse");
415 }
416
417
424
425 inline
426 void
427 mex_create_string_cell_array( mxArray * & arg, vector<string> const & str_vec ) {
428 // Crea un cell array MATLAB con lo stesso numero di elementi del vettore di stringhe
429 arg = mxCreateCellMatrix(str_vec.size(), 1);
430
431 // Riempie il cell array con le stringhe C++
432 for ( size_t i{0}; i < str_vec.size(); ++i ) {
433 mxArray *str = mxCreateString(str_vec[i].data()); // Crea una stringa MATLAB dalla stringa C++
434 mxSetCell(arg, i, str); // Imposta la stringa nella posizione corretta del cell array
435 }
436 }
437
438 /*
439 Class Handle by Oliver Woodford
440
441 https://it.mathworks.com/matlabcentral/fileexchange/38964-example-matlab-class-wrapper-for-a-c++-class
442 */
443
453 template <typename base>
455 uint32_t m_signature{CLASS_HANDLE_SIGNATURE};
456 base * m_ptr{nullptr};
457 string m_name;
458
459 public:
460
467
474
480 explicit
482 : m_ptr(ptr)
483 , m_name(typeid(base).name())
484 {}
485
490 { m_signature = 0; delete m_ptr; m_ptr = nullptr; }
491
499 bool is_valid()
500 { return ((m_signature == CLASS_HANDLE_SIGNATURE) &&
501 !strcmp(m_name.data(), typeid(base).name())); }
502
508 base * ptr() { return m_ptr; }
509 };
510
521 template <typename base>
522 inline
523 mxArray *
524 mex_convert_ptr_to_mx( base * ptr ) {
525 mexLock();
526 mxArray *out = mxCreateNumericMatrix(1, 1, mxUINT64_CLASS, mxREAL);
527 *((uint64_t *)mxGetData(out)) = reinterpret_cast<uint64_t>(
529 );
530 return out;
531 }
532
544 template <typename base>
545 inline
546 mex_class_handle<base> *
547 mex_convert_mx_to_handle_ptr( mxArray const * in ) {
548 if ( mxGetNumberOfElements(in) != 1 ||
549 mxGetClassID(in) != mxUINT64_CLASS ||
550 mxIsComplex(in) ) {
551 mexErrMsgTxt( "Input must be an uint64 scalar." );
552 }
553 mex_class_handle<base> * ptr = reinterpret_cast<mex_class_handle<base> *>(
554 *((uint64_t *)mxGetData(in))
555 );
556 if ( !ptr->is_valid() ) mexErrMsgTxt( "Handle not valid." );
557 return ptr;
558 }
559
570 template <typename base>
571 inline
572 base *
573 mex_convert_mx_to_ptr( mxArray const * in ) {
575 }
576
586 template <typename base>
587 inline
588 void
589 mex_destroy_object( mxArray const * & in ) {
590 if ( in != nullptr ) delete mex_convert_mx_to_handle_ptr<base>(in);
591 in = nullptr;
592 mexUnlock();
593 }
594
596
597}
598
599//
600// eof: mex_utils.hxx
601//
A class template that manages a C++ object for use with MATLAB.
Definition mex_utils.hxx:454
base * ptr()
Retrieves the pointer to the managed C++ object.
Definition mex_utils.hxx:508
bool is_valid()
Checks if the handle is valid.
Definition mex_utils.hxx:499
mex_class_handle< base > const & operator=(mex_class_handle< base > const &)=delete
Deleted copy assignment operator.
mex_class_handle(base *ptr)
Constructor that initializes the handle with a pointer to a C++ object.
Definition mex_utils.hxx:481
~mex_class_handle()
Destructor that cleans up the managed object.
Definition mex_utils.hxx:489
mex_class_handle()=delete
Deleted default constructor.
void mex_set_scalar_int64(mxArray *&arg, int64_t value)
Sets a scalar 64-bit integer value in the output argument.
Definition mex_utils.hxx:289
double const * mex_vector_pointer(mxArray const *arg, mwSize &sz, string_view msg)
Gets a pointer to a vector from the input argument.
Definition mex_utils.hxx:211
void mex_error_message(string_view msg)
Sends an error message to MATLAB.
Definition mex_utils.hxx:98
bool mex_is_scalar(mxArray const *arg, string_view msg)
Checks if the input argument is a scalar.
Definition mex_utils.hxx:109
void mex_create_string_cell_array(mxArray *&arg, vector< string > const &str_vec)
Creates a MATLAB cell array and fills it with a vector of C++ strings.
Definition mex_utils.hxx:427
mex_class_handle< base > * mex_convert_mx_to_handle_ptr(mxArray const *in)
Converts a MATLAB mxArray back to a mex_class_handle pointer.
Definition mex_utils.hxx:547
double const * mex_matrix_pointer(mxArray const *arg, mwSize &nr, mwSize &nc, string_view msg)
Gets a pointer to a matrix from the input argument.
Definition mex_utils.hxx:239
mxArray * mex_convert_ptr_to_mx(base *ptr)
Converts a pointer to a mex_class_handle into a MATLAB mxArray.
Definition mex_utils.hxx:524
bool mex_get_bool(mxArray const *arg, string_view msg)
Gets a boolean value from the input argument.
Definition mex_utils.hxx:146
void mex_destroy_object(mxArray const *&in)
Destroys the object wrapped by the mex_class_handle.
Definition mex_utils.hxx:589
base * mex_convert_mx_to_ptr(mxArray const *in)
Converts a MATLAB mxArray to a pointer of the wrapped C++ object.
Definition mex_utils.hxx:573
void mex_set_scalar_value(mxArray *&arg, double value)
Sets a scalar value in the output argument.
Definition mex_utils.hxx:263
void mex_set_scalar_int32(mxArray *&arg, int32_t value)
Sets a scalar integer value in the output argument.
Definition mex_utils.hxx:276
double * mex_create_matrix_value(mxArray *&arg, mwSize nrow, mwSize ncol)
Creates a numeric matrix of type double and returns a pointer to its data.
Definition mex_utils.hxx:360
double mex_get_scalar_value(mxArray const *arg, string_view msg)
Gets the scalar value from the input argument.
Definition mex_utils.hxx:125
void mex_set_scalar_bool(mxArray *&arg, bool value)
Sets a boolean value in the output argument.
Definition mex_utils.hxx:302
int32_t * mex_create_matrix_int32(mxArray *&arg, mwSize nrow, mwSize ncol)
Creates a numeric matrix of type int32 and returns a pointer to its data.
Definition mex_utils.hxx:320
int mex_create_sparse_matrix(size_t nnz, size_t nrows, size_t ncols, I i_rows[], I j_cols[], R vals[], mxArray *arg_out[])
Creates a sparse matrix in MATLAB format.
Definition mex_utils.hxx:386
int64_t * mex_create_matrix_int64(mxArray *&arg, mwSize nrow, mwSize ncol)
Creates a numeric matrix of type int64 and returns a pointer to its data.
Definition mex_utils.hxx:340
int64_t mex_get_int64(mxArray const *arg, string_view msg)
Gets a 64-bit integer value from the input argument.
Definition mex_utils.hxx:160
#define UTILS_MEX_ASSERT0(COND, MSG)
Definition mex_utils.hxx:75
#define UTILS_MEX_ASSERT(COND, FMT,...)
Definition mex_utils.hxx:77
#define CLASS_HANDLE_SIGNATURE
Definition mex_utils.hxx:31
Definition SystemUtils.cc:39