Properly resizing mxCreateStructMatrix post-2018a?

1 visualizzazione (ultimi 30 giorni)
I've parsed the documentation as best I can, but I'm not entirely clear I'm digesting it correctly. I'm trying to resize an mxArray created with mxCreateStructMatrix. To be clear, I need to be able to support both the newer post-2018a API, and the old API. I do not have a priori knowledge of how many elements will be in this particular structure until after it has been created. To further complicate things, this is actually a child structure that is just an element of a larger structure, but I don't think that's germane to the question below.
a = mxCreateStructMatrix( 1, 1, sizeof(struct_names)/sizeof(struct_names[0]), struct_names);
...then, sometime later:
record = mxGetFieldByNumber(parent_struct, 0, 17); /* get mxArray pointer to what we called "a" above */
if (input_data_count > 1) {
void *b = mxGetData(record);
size_t size = mxGetElementSize(record);
b = mxRealloc(b, size * input_data_count);
mxSetN( record, input_data_count );
mxSetData(record, b);
}
I would then proceed to populate the elements of "record".
Is this implementation correct, or will I be corrupting memory here at some point (I don't want to just "plug and pray", since memory issues don't always show up straight away)? I'm assuming the mxArray in this case is considered a "nonnumeric array" as far as the documentation is concerned?
Thanks

Risposte (1)

James Tursa
James Tursa il 29 Set 2021
Modificato: James Tursa il 29 Set 2021
TMW doesn't publish the complete rules for how the data areas of structs are organized, but historically they have always put each element's field pointers bunched together. So the general idea of your scheme should work, but some potential issues I note are:
Your realloc code assumes the current size is 1:
if (input_data_count > 1) {
Maybe this is a good assumption (I don't know because you haven't shown the complete code), but for robustness maybe consider something like this instead:
if (input_data_count > mxGetN(record)) {
The amount of "data" storage for each element of a struct is (number of fields) * (size of mxArray pointer). So as long as that is what mxGetElementSize(record) returns then you should be OK. I don't recall what mxGetElementSize( ) does in this case, so you should check this. If not as expected, then you might be forced to manually calculate this. E.g.,
size_t size = mxGetNumberOfFields(record) * sizeof(mxArray *);
The fact that record is a child of a larger struct would only be relevant if there were any variable or data sharing going on in your program. If everything is created from scratch inside your mex routine and you don't specifically code such sharing, then there shouldn't be any sharing. But if this larger struct is being passed back & forth between your mex routine and MATLAB then there could be sharing going on, in which case your manipulation via realloc could have unintended side effects to other variables.
Finally, I don't see anything in your code that depends on any particular feature of R2018a mxArray model vs old mxArray model, so it should work in both cases. There have been a lot of internal mxArray header changes these past few years, and a change in how complex data is stored, but I don't see any of these changes affecting your code for manipulating a struct data area.

Categorie

Scopri di più su Data Type Conversion in Help Center e File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by