Breaking changes for C++ API?

Updated: I made a minimal example of the issue. Older versions of MATLAB (I was using 2015b) work fine with this code. MATLAB 2019b throws a NoActiveContextTypeError exception. It is possible to continue past the exception, but I'm not sure that this is safe.
I've attached a visual studio solution that points to my matlab installation libraries. You might need to change the path in project settings -- I have it pointing at D:\MATLAB\R2019b in three places:
  • VC++ Directories / Include Directories (D:\MATLAB\R2019b\extern\include)
  • C/C++ General / Additional Include Directories (D:\MATLAB\R2019b\extern\include)
  • Linker / General / Additional Library Directories (D:\MATLAB\R2019b\extern\lib\win64\microsoft)
  • Also call "matlab /regserver" in MATLAB\R2019b\bin\win64 if you need to
As discussed below, adding an initial field name instead of NULL doesn't change the behavior.
What is the reason for the exception and is this code safe?
-------------- Original Question --------------
I have C++ code that starts a matlab session using engOpenSingleUse(). It builds data structures using mxCreateStructMatrix() and sends them over to Matlab using engPutVariable(). It executes some user code via engEvalString(), and fetches the results with engGetVariable(). This has all been working fine for a few years. Recently I was unable to get my code to work with MATLAB 2019b. It works fine with 2015b. When linking with 2019b stuff I get the following cryptic error on mxCreateStructMatrix():
engOpenSingleUse() seems to work. Was mxCreateStructMatrix depricated or were breaking changes made to the interface? I am confused about the difference between the C Matrix API and the newer C++ API that was released around 2017b.
I am looking for a solution we can deploy for calling MATLAB code and sending data from a C++ application that is compatible with a wide range of MATLAB versions.

2 Comments

James Tursa
James Tursa on 25 Sep 2019
Edited: James Tursa on 25 Sep 2019
What is the SetField( ) function? Something you wrote? How does this function work when the struct in question does not have the given field? Can you show the code for this?
The new C++ API interface is completely different from the C API that you are currently using. You would have to overhaul your code to use the C++ API, which may not be worth it to you, particularly if you want to support older versions of MATLAB.

Sign in to comment.

Answers (2)

James Tursa
James Tursa on 25 Sep 2019
Edited: James Tursa on 25 Sep 2019
The current online doc for mxCreateStructMatrix( ) says the last argument must contain "... one or more field names ...", which your code does not do. If I look at the doc from an older version of MATLAB (R2014a) it simply says "List of field names". So maybe something has changed, and it won't take a NULL for this anymore.
Do you know all the field names ("generators", "primary_loads", etc.) in advance? Can you create the struct up front with all of those field names instead of trying to add them in piecemeal later on?
Or, create the struct with one field name (e.g., "dummy" or "unused") that you don't use, and leave all your current code the same. You could even remove this field later if you didn't want it hanging around and cluttering up your field names. Removing a field like this should be a very fast operation, since only a few mxArray pointers get moved in memory ... no mxArray data actually gets moved.

9 Comments

Thanks for the suggestions, James. Adding a dummy field to the arguments of mxCreateStructMatrix doesn't seem to help. Here's what I tried (same error):
Capture.PNG
SetField is a method I wrote. It calls mxSetField and a few other API methods to add a new field to the mxArray pointed to by sp_. But, execution never makes it that far.
What is a NoActiveContextTypeError? It appear to be something mathworks wrote, because I can't find anything about it on google.
I don't know any details about NoActiveContextTypeError ... I was just guessing that it had something to do with a NULL pointer where it was expecting content.
For your fns, I think you are missing one level of indirection. That last argument needs to be a (char **) type. (I.e., from an array of char *). Maybe try this instead:
sp_ = mxCreateStructMatrix(1, 1, 1, &fns);
But even with that I still think you've got the wrong type for fns to hold the pointer. Maybe just do it like this:
const char *fns[1] = {"test"};
sp_ = mxCreateStructMatrix(1, 1, 1, fns);
Just tried that, same result.Capture.PNG
James Tursa
James Tursa on 26 Sep 2019
Edited: James Tursa on 26 Sep 2019
??? ... what the heck is going on? I need to think about this some more ...
Can you show me the SetField( ) code?
Did you also write ConvertToMxArray( )?
Thanks James. Small update: the execution seems to continue normally if I just continue past the exception. So I finished up some updates that I was trying to do in the first place. Now I'll put together a full minimal example that doesn't include all our proprietary code, and I'll post that when it's ready...
Ok, attached is my working example in a visual studio solution. You might need to reconfigure the project settings -- I have it pointing at D:\MATLAB\R2019b in three places:
  • VC++ Directories / Include Directories (D:\MATLAB\R2019b\extern\include;)
  • C/C++ General / Additional Include Directories (D:\MATLAB\R2019b\extern\include;)
  • Linker / General / Additional Library Directories (D:\MATLAB\R2019b\extern\lib\win64\microsoft)
You might need to modify those paths to the location of your install. Also note that I'm running in x64 to match the x64 arcitecture of all the MATLAB stuff. to Here's what I see:
Capture.PNG
I haven't looked at your zip file or tried to set anything up, but I did notice the following with your latest image post.
Your use of the ret variable is incorrect and also the source of a crash. You are supposed to pass in the address of an int so that engOpenSIngleUse( ) can return a value in it. I.e., you are supposed to pass a pointer to valid memory. But what you have done is to essentially pass a NULL pointer into the function (the ret value is 0) which when deferenced inside the function will result in an invalid memory access and I would expect a crash.
Fix all this up first to make sure it isn't contributing to your problems.
int ret; // make ret an int, not a pointer to int
Engine *ep = engOpenSingleUse( "", NULL, &ret ); // pass the address of ret
You should probably check that the values of ep and sp are not NULL before using them, btw.
Okay, made those changes. The autos appear to be resolving to Engine* and mxArray* respectively, not ints, so I'm not sure I understand what you're saying there, but they are declared explicitly as class members in production anyway. The int pointer set to null was just sloppiness from trying to go too fast-- sorry about that. In the production code I check for error conditions, but leaving all that out here for simplicity. Same exception now. Attached is the code with those changes. Thanks for the support!
Capture.PNG
James Tursa
James Tursa on 26 Sep 2019
Edited: James Tursa on 26 Sep 2019
"The autos appear to be resolving to Engine* and mxArray* respectively, not ints, so I'm not sure I understand what you're saying there"
That was a C response by me, which I removed from my post once I remembered this was C++ code, but you looked at my response before I removed that section. :)
(And I don't think I have given you much support yet ...)

Sign in to comment.

Paul Williams
Paul Williams on 27 Sep 2019
If you have more than one MATLAB installed on your system it could be loading the run-time libraries from an earlier version.

Categories

Products

Release

R2019b

Tags

Asked:

on 25 Sep 2019

Edited:

on 1 Oct 2019

Community Treasure Hunt

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

Start Hunting!