1
votes

Using MATLAB Compiler Runtime (mcr) i have created dll of the a matlab file. I can use the function and pass all the variables to the function easily and without any problem.

My problem is when I have a class with "mwArray" as a variable in it, like:

#include <samplemmfile.h>
#include <mclmcr.h>
#include <stdio.h>

class MModel{

int x;
mwArray y;
};

and then I create an object from it, application in run-time throws an exception in "mclcppclass.h" header file:

Access violation executing location 0X0000000000. 

It would be quite expensive to wrap and convert all input files to the matlab format every time that I want to call those functions, therefore was wondering is there any solution for this problem?

Thanks,

2
Would it make sense to try making y a pointer to an mwArray, and then calling new in the constructor?Lukeclh
did you remember to initialize the MCR runtime (mclInitializeApplication) and library (libXXXInitialize) before using any of it? You have to be careful about the order of how things are constructed when you have classes..Amro
Using pointer didn't work actually! and yep, I did initialized the application and lib first! I can use them in a function easily, but I should pass them all the time to matlab format that makes it uncomfortable!Ishmael mp

2 Answers

1
votes

Thanks, my problem has been solved actually! the issue is regarding the fact that initialization should be done before creating any instance of the class which contains mwArray object.

For example the following code is gonna crash at the beginning, :

Class1.h:

#include "libInnerProduct.h" 

class Class1
{
public:
Class1()
: a(1, 2, mxDOUBLE_CLASS), b(1, 2, mxDOUBLE_CLASS) {
    double aa[] = {1 , 2};
    double bb[] = {5 , 7};
    a.SetData(aa, 2);
    b.SetData(bb, 2);
}
double innerproduct() {
    mwArray c;
    InnerProd(1, c, a, b);
    return (double)c;
}
private:
mwArray a, b;
};

Class2.h:

 #include "Class1.h" 
 #include <mclmcr.h>
 #include <mclcppclass.h>

class Class2
{
public:
Class2(){
    if (!mclInitializeApplication(NULL,0) || !libInnerProductInitialize())  {
          std::cerr << "failed to initialize" << std::endl;
          exit(1);
    }
    obj=new Class1();
}
~Class2(){
    libInnerProductTerminate();   
    mclTerminateApplication();
}
double inp(){
    return obj->innerproduct();
}
private:
Class1* obj;
};

int main()
{
    Class2 obj;
    double sum = obj.inp();
    std::cout << sum << std::endl;  
    return 0;
} 

but if you put the initialization part before getting instance from Class2, everything will be fine. In addition, you can not have an instance of the Class2 out of the main too!

Cheers,

0
votes

I tried with a simple example on my end (I'm reusing a previous example of mine), but I cannot reproduce the problem.

The MATLAB function we are packaging is the following:

MyAdd.m

function c = MyAdd(a,b)
    c = a + b;
end

Compiled into a C++ shared library using mcc compiler:

>> mcc -N -W cpplib:libMyAdd -T link:lib MyAdd.m -v

Next here is a C++ program to test the library. I created a class that holds two mwArray instances:

testMyAdd.cpp

#include "libMyAdd.h"    // generated library

class MyClass
{
  public:
    MyClass()
    : a(2, 2, mxDOUBLE_CLASS, mxREAL), b(2, 2, mxDOUBLE_CLASS, mxREAL) {
        double aa[] = {1.0, 2.0, 3.0, 4.0};
        double bb[] = {5.0, 6.0, 7.0, 8.0};
        a.SetData(aa, 4);
        b.SetData(bb, 4);
    }
    mwArray add() {
        mwArray c;
        MyAdd(1, c, a, b);
        return c;
    }
  private:
    mwArray a, b;
};

int main()
{
    if (!mclInitializeApplication(NULL,0) || !libMyAddInitialize())  {
        std::cerr << "failed to initialize" << std::endl;
        return -1;
    }

    try {
        MyClass obj;
        mwArray sum = obj.add();
        std::cout << "a + b = \n" << sum << std::endl;
    } catch (const mwException& e) {
        std::cerr << e.what() << std::endl;
        return -2;
    } catch (...) {
        std::cerr << "Unexpected error thrown" << std::endl;
        return -3;
    } 

    libMyAddTerminate();   
    mclTerminateApplication();
    return 0;
}

The above runs just fine:

>> mbuild testMyAdd.cpp libMyAdd.lib -v
C:\> testMyAdd.exe
a + b =  
     6    10 
     8    12