Setting fields of a Matlab struct in C++
7 ビュー (過去 30 日間)
古いコメントを表示
I have a compiled Matlab function that takes a structure as input. I'm trying to initialize that structure from C++, using the mwArray framework. Let's say the structure just has fields "a", "b", and "c".
First I'm going to create a 1x1 structure array with those fields (I'm not going to delete anything in this example, but assume deletion happens later at the right time):
fields = new char*[3];
fields[0] = "a"; fields[1] = "b"; fields[2] = "c";
mwSize dims[2] = {1,1};
mwArray* inputArray = new mwArray(2, dims, 3, (const char**)fields);
I can confirm that this array has 3 fields with the right names and 1 element using NumberOfFields(), GetFieldName(), and NumberOfElements().
Now I'm going to make mwArray's that I'll use to set the fields:
double a=1,b=2,c=3;
mwArray field0Value(1, 1, mxDOUBLE_CLASS, mxREAL);
mwArray field1Value(1, 1, mxDOUBLE_CLASS, mxREAL);
mwArray field2Value(1, 1, mxDOUBLE_CLASS, mxREAL);
field0Value.SetData(&a, 1);
field1Value.SetData(&b, 1);
field2Value.SetData(&c, 1);
Now I have three individual one-element double arrays. I can confirm that these are properly set using NumberOfElements() and GetData().
Now here's the core of my question...
* How do I assign these values to the fields of inputArray? *
My first instinct, consistent with the only example I could find online, was to do this:
inputArray->Get(fields[0],1,1).Set(field0Value);
But this doesn't work... calling "Get(fields[0],1,1)" seems to produce a deep copy of the field I'm interested in, so this line does nothing to inputArray. If I call:
inputArray->Get(fields[0],1,1).NumberOfElements()
...immediately after executing the "Set()", it still has 0 elements. If I store the temporary variable I get from inputArray->Get(fields[0],1,1), I can set its data. This all tells me that the Get() operation is performing a copy, and I'm not really accessing inputArray.
This is all confirmed when I try to pass inputArray to my Matlab function; it's empty.
* So how do I actually put data into a struct array? *
Thanks!
-Dan
0 件のコメント
回答 (6 件)
Kaustubha Govind
2011 年 8 月 17 日
I think you might need to use operator(). Try:
inputArray(fields[0],1,1) = field0Value;
0 件のコメント
Daniel
2011 年 8 月 17 日
2 件のコメント
Kaustubha Govind
2011 年 8 月 18 日
Strange. This solution seems to suggest that using Get() like you did should work: http://www.mathworks.com/support/solutions/en/data/1-2VHBW8/index.html
The only difference is that you are using an mwArray pointer, but I can't think of why that could be a problem.
ClemensM
2015 年 7 月 2 日
Hi.
I am having exact the same problem on Windows. On Linux i have used mwArray structure creation exactly like described above and it works.
The thing that really is really annoying is that this is at least since MATLAB R2009a like that and still is in R2014a. It is a little hard to believe that an API that is unsusable on Windows has never been fixed.
Is it possible that somewone at Mathworks sets up a little test example on Windows and if successful provides it to us?
Thanks,
Clemens
Alexey Krutikhin
2015 年 8 月 26 日
I found a solution - try to use GetA() instead of Get(). It works for me.
0 件のコメント
Steven Lord
2015 年 8 月 26 日
I haven't tried this, and this is well outside my usual area of expertise, but from reading the documentation and cobbling together pieces of examples I think something like this should work.
// Create the struct and get an mwArray for its field 'a'
const char* fields[] = {"a", "b", "c"};
mwArray mystruct(1, 1, 3, fields);
mwArray fieldA = mystruct.Get("a", 1, 1);
// Create the data to store in the field
mwArray f(2, 2, mxDOUBLE_CLASS);
f(1, 1) = 1;
f(1, 2) = 2;
f(2, 1) = 3;
f(2, 2) = 4;
// This last is from the documentation for the SET method, described as "Assign shared copy of"
// input array to currently referenced cell for arrays of type mxCELL_CLASS and mxSTRUCT_CLASS."
fieldA.Set(f);
0 件のコメント
Alan Frankel
2019 年 6 月 12 日
編集済み: Alan Frankel
2019 年 6 月 12 日
I tried this with both MATLAB R2014b and R2019b. I found that, unlike Daniel, I am able to set the struct field using mwArray (C++) code whether I:
- chain the calls to Get() and Set(), or
- store the result of the Get() call in a named variable before calling Set() on it
Here's my version of the driver code (where my code does not call "new", so does not need to call "delete"):
const char* fields[] = {"a", "b", "c"};
mwSize dims[2] = {1,1};
mwArray inputArray(2, dims, 3, fields);
double a=1,b=2,c=3;
mwArray field0Value(1, 1, mxDOUBLE_CLASS, mxREAL);
mwArray field1Value(1, 1, mxDOUBLE_CLASS, mxREAL);
mwArray field2Value(1, 1, mxDOUBLE_CLASS, mxREAL);
field0Value.SetData(&a, 1);
field1Value.SetData(&b, 1);
field2Value.SetData(&c, 1);
std::cout << "EXAMPLE 1: Chain the calls to Get() and Set()." << std::endl;
std::cout << "before: inputArray.Get(fields[0],1,1).NumberOfElements(): " <<
inputArray.Get(fields[0],1,1).NumberOfElements() << std::endl;
std::cout << "before: inputArray.Get(fields[0],1,1): "
<< inputArray.Get(fields[0],1,1) << std::endl;
inputArray.Get(fields[0],1,1).Set(field0Value);
std::cout << "after: inputArray.Get(fields[0],1,1).NumberOfElements(): " <<
inputArray.Get(fields[0],1,1).NumberOfElements() << std::endl;
std::cout << "after: inputArray.Get(fields[0],1,1): "
<< inputArray.Get(fields[0],1,1) << std::endl << std::endl;
std::cout << "EXAMPLE 2: Don't chain the calls to Get() and Set()." << std::endl;
std::cout << "before: inputArray.Get(fields[1],1,1).NumberOfElements(): " <<
inputArray.Get(fields[1],1,1).NumberOfElements() << std::endl;
std::cout << "before: inputArray.Get(fields[1],1,1): "
<< inputArray.Get(fields[1],1,1) << std::endl;
mwArray field = inputArray.Get(fields[1],1,1);
field.Set(field1Value);
std::cout << "after: inputArray.Get(fields[1],1,1).NumberOfElements(): " <<
inputArray.Get(fields[1],1,1).NumberOfElements() << std::endl;
std::cout << "after: inputArray.Get(fields[1],1,1): "
<< inputArray.Get(fields[1],1,1) << std::endl;
And here's the output:
EXAMPLE 1: Chain the calls to Get() and Set().
before: inputArray.Get(fields[0],1,1).NumberOfElements(): 0
before: inputArray.Get(fields[0],1,1): []
after: inputArray.Get(fields[0],1,1).NumberOfElements(): 1
after: inputArray.Get(fields[0],1,1): 1
EXAMPLE 2: Don't chain the calls to Get() and Set().
before: inputArray.Get(fields[1],1,1).NumberOfElements(): 0
before: inputArray.Get(fields[1],1,1): []
after: inputArray.Get(fields[1],1,1).NumberOfElements(): 1
after: inputArray.Get(fields[1],1,1): 2
0 件のコメント
参考
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!