【问题标题】:C++: mwArray as a variable in a c++ classC++:mwArray 作为 C++ 类中的变量
【发布时间】:2014-09-19 14:30:49
【问题描述】:

使用 MATLAB Compiler Runtime (mcr) 我创建了一个 matlab 文件的 dll。我可以使用该函数并将所有变量轻松传递给该函数,没有任何问题。

我的问题是当我有一个带有“mwArray”作为变量的类时,例如:

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

class MModel{

int x;
mwArray y;
};

然后我从它创建一个对象,运行时应用程序在“mclcppclass.h”头文件中引发异常:

Access violation executing location 0X0000000000. 

每次我想调用这些函数时,将所有输入文件打包并转换为 matlab 格式会非常昂贵,因此想知道这个问题有什么解决方案吗?

谢谢,

【问题讨论】:

  • 尝试将 y 设为 mwArray 的指针,然后在构造函数中调用 new 是否有意义?
  • 您是否记得在使用之前初始化 MCR 运行时 (mclInitializeApplication) 和库 (libXXXInitialize)?当你有类时,你必须注意事物的构造顺序。..
  • 使用指针实际上不起作用!是的,我确实首先初始化了应用程序和库!我可以轻松地在函数中使用它们,但我应该一直将它们传递给 matlab 格式,这会让人不舒服!

标签: c++ matlab matlab-compiler


【解决方案1】:

谢谢,我的问题实际上已经解决了!问题在于,应该在创建包含 mwArray 对象的类的任何实例之前完成初始化。

例如下面的代码一开始就会崩溃:

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

但是如果你把初始化部分放在从 Class2 获取实例之前,一切都会好起来的。另外,你不能有一个Class2的实例掉main呢!

干杯,

【讨论】:

    【解决方案2】:

    我尝试了一个简单的示例(我正在重复使用我的 previous example),但我无法重现该问题。

    我们打包的MATLAB函数如下:

    MyAdd.m

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

    使用mcc编译器编译成C++共享库:

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

    【讨论】:

    • 真的很棒!但这里有问题:把“MyClass obj;”出你的主力!或在另一个类中作为“MyClass”类的对象。您将遇到突然出现的错误!
    • @Ishmaelmp:全局变量在程序启动时被初始化BEFORE主函数有机会运行,所以MyClass的构造函数会在MCR初始化之前运行(这很糟糕!).. 就像我之前在 cmets 中所说的那样,您必须注意事物的初始化顺序...您必须修改类 MyClass 以管理其自己的依赖项,使用某种静态成员,以确保在实例化类之前首先调用 mclInitializeApplication
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-16
    相关资源
    最近更新 更多