С++: mwArray как переменная в классе С++

Используя MATLAB Compiler Runtime (mcr), я создал dll файла Matlab. Я могу использовать функцию и легко и без проблем передать ей все переменные.

Моя проблема в том, что у меня есть класс с "mwArray" в качестве переменной, например:

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

class MModel{

int x;
mwArray y;
};

а затем я создаю из него объект, приложение во время выполнения выдает исключение в заголовочном файле «mclcppclass.h»:

Access violation executing location 0X0000000000. 

Было бы довольно дорого оборачивать и преобразовывать все входные файлы в формат Matlab каждый раз, когда я хочу вызывать эти функции, поэтому мне было интересно, есть ли какое-либо решение этой проблемы?

Спасибо,


person Ishmael mp    schedule 19.09.2014    source источник
comment
Имеет ли смысл попытаться сделать y указателем на mwArray, а затем вызывать new в конструкторе?   -  person Lukeclh    schedule 19.09.2014
comment
Вы не забыли инициализировать среду выполнения MCR (mclInitializeApplication) и библиотеку (libXXXInitialize) перед их использованием? Вы должны быть осторожны с порядком построения вещей, когда у вас есть классы.   -  person Amro    schedule 19.09.2014
comment
Использование указателя на самом деле не сработало! и да, я сначала инициализировал приложение и библиотеку! Я могу легко использовать их в функции, но я должен все время передавать их в формат Matlab, что делает его неудобным!   -  person Ishmael mp    schedule 19.09.2014


Ответы (2)


Спасибо, моя проблема действительно решена! проблема связана с тем, что инициализация должна выполняться перед созданием любого экземпляра класса, содержащего объект mwArray.

Например, следующий код вылетит в начале:

Класс1.ч:

#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;
};

Класс 2.ч:

 #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;
} 

но если вы поставите часть инициализации перед получением экземпляра из Class2, все будет хорошо. Кроме того, вы не можете иметь экземпляр класса 2 вне основного!

Ваше здоровье,

person Ishmael mp    schedule 02.10.2014

Я попытался использовать простой пример со своей стороны (я повторно использую предыдущий пример), но я не могу воспроизвести проблема.

Функция MATLAB, которую мы упаковываем, выглядит следующим образом:

MyAdd.m

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

Скомпилировано в разделяемую библиотеку C++ с помощью компилятора mcc:

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

Далее идет программа на C++ для тестирования библиотеки. Я создал класс, содержащий два экземпляра mwArray:

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;
}

Вышеприведенное работает нормально:

>> mbuild testMyAdd.cpp libMyAdd.lib -v
C:\> testMyAdd.exe
a + b =  
     6    10 
     8    12 
person Amro    schedule 19.09.2014
comment
Это здорово на самом деле! но вот проблема: поместите объект MyClass; из вашего основного! или в другом классе как объект из класса MyClass. У вас будет ошибка, которая из ниоткуда! - person Ishmael mp; 25.09.2014
comment
@Ishmaelmp: глобальные переменные инициализируются при запуске программы ДО, когда основная функция получает возможность запуститься, поэтому конструктор MyClass будет запускаться до инициализации MCR (что плохо!). Как и я ранее сказано в комментариях, вы должны быть осторожны с порядком инициализации вещей... Вам придется изменить класс MyClass для управления его собственными зависимостями, используя какие-то статические члены, чтобы гарантировать, что mclInitializeApplication вызывается первым, до создания экземпляра класса - person Amro; 26.09.2014