4

这个问题的起源来自这里How to use "global static" variable in matlab function called in c

我正在尝试将“全局变量”封装到一个对象中。但是我不知道如何使用 MATLAB Compiler (mcc)将 matlab 类导出到 c++

为此,我只是尝试了标准命令

Matlab 命令

mcc -W cpplib:Vowel4 -T link:lib Vowel4.m

Matlab 脚本

classdef Vowel4

  properties
    x
    y
  end

  methods
    Vowel4
    A
    B
  end

end

生成的库实际上是独立的函数而不是 c++ 类。

如何将 Matlab 中的类编译成 c++ 类?

我一直在寻找答案,但没有找到。

显然 matlab 命令不适合这种场景。但是我找不到任何关于将 Matlab 类构建到 c++ 类中的信息。

===========================编辑======================= =

实际cpp代码如下:@Alan

mclInitializeApplication(NULL, 0);
loadDataInitialize();
soundByCoefInitialize();
loadData(); 

mwArray F(4, 1, mxDOUBLE_CLASS);
float test[4];

for ( ;; ){
    const Frame frame = controller.frame();
    const FingerList fingers = frame.fingers();
    if ( !fingers.empty() ){
        for ( int i = 0; i < 4; i ++ ){
            double v = fingers.count() > i ? (fingers[i].tipPosition().y / 50) - 2 : 0;
            F(i+1,1) = v;
            test[i] = v;
            cout << v << ' ';
        }
        cout << endl;
        soundByCoef(F);
    }
}

这里的 matlabA() 对应于 loadData(),它加载数据,soundByCoef(F) 对应于 matlabB(),它在主循环中完成工作。

4

2 回答 2

6

正如 Alan 所指出的,只是建议使用句柄类作为全局变量的容器(这样做的好处是可以通过引用传递这样的对象)。创建的对象不打算由您的 C++ 代码直接操作(它将存储在通用mxArray/mwArrayC/C++ 结构中)。

我所知,在使用 MATLAB 编译器构建共享库时,您不能直接将 classdef 样式的 MATLAB 类编译为适当的 C++ 类。它只支持构建常规功能。您可以为 MATLAB 类成员方法创建功能接口,但那是另一回事......

也许一个完整的例子将有助于说明我的想法。首先让我们在 MATLAB 端定义代码:

全球数据.m

这是用于存储全局变量的句柄类。

classdef GlobalData < handle
    %GLOBALDATA  Handle class to encapsulate all global state data.
    %
    % Note that we are not taking advantage of any object-oriented programming
    % concept in this code. This class acts only as a container for publicly
    % accessible properties for the otherwise global variables.
    %
    % To manipulate these globals from C++, you should create the class API
    % as normal MATLAB functions to be compiled and exposed as regular C
    % functions by the shared library.
    % For example: create(), get(), set(), ...
    %
    % The reason we use a handle-class instead of regular variables/structs
    % is that handle-class objects get passed by reference.
    %

    properties
        val
    end
end

create_globals.m

作为上述类的构造函数的包装函数

function globals = create_globals()
    %CREATE_GLOBALS  Instantiate and return global state

    globals = GlobalData();
    globals.val = 2;
end

fcn_add.m, fcn_times.m

将作为 C++ 函数公开的 MATLAB 函数

function out = fcn_add(globals, in)
    % receives array, and return "input+val" (where val is global)

    out = in + globals.val;
end

function out = fcn_times(globals, in)
    % receives array, and return "input*val" (where val is global)

    out = in .* globals.val;
end

将上述文件存储在当前目录中,让我们使用 MATLAB 编译器构建 C++ 共享库:

>> mkdir out
>> mcc -W cpplib:libfoo -T link:lib -N -v -d ./out create_globals.m fcn_add.m fcn_times.m

您应该期待以下生成的文件(我在 Windows 机器上):

./out/libfoo.h
./out/libfoo.dll
./out/libfoo.lib

接下来,我们可以创建一个示例 C++ 程序来测试该库:

主文件

// Sample program that calls a C++ shared library created using
// the MATLAB Compiler.

#include <iostream>
using namespace std;

// include library header generated by MATLAB Compiler
#include "libfoo.h"

int run_main(int argc, char **argv)
{
    // initialize MCR
    if (!mclInitializeApplication(NULL,0)) {
        cerr << "Failed to init MCR" << endl;
        return -1;
    }

    // initialize our library
    if( !libfooInitialize() ) {
        cerr << "Failed to init library" << endl;
        return -1;
    }

    try {
        // create global variables
        mwArray globals;
        create_globals(1, globals);

        // create input array
        double data[] = {1,2,3,4,5,6,7,8,9};
        mwArray in(3, 3, mxDOUBLE_CLASS, mxREAL);
        in.SetData(data, 9);

        // create output array, and call library functions
        mwArray out;
        fcn_add(1, out, globals, in);
        cout << "Added matrix:\n" << out << endl;
        fcn_times(1, out, globals, in);
        cout << "Multiplied matrix:\n" << out << endl;
    } catch (const mwException& e) {
        cerr << e.what() << endl;
        return -1;
    } catch (...) {
        cerr << "Unexpected error thrown" << endl;
        return -1;
    }

    // destruct our library
    libfooTerminate();

    // shutdown MCR
    mclTerminateApplication();

    return 0;
}

int main()
{
    mclmcrInitialize();
    return mclRunMain((mclMainFcnType)run_main, 0, NULL);
}

让我们构建独立程序:

>> mbuild -I./out main.cpp ./out/libfoo.lib -outdir ./out

最后运行可执行文件:

>> cd out
>> !main
Added matrix: 
     3     6     9 
     4     7    10 
     5     8    11 
Multiplied matrix: 
     2     8    14 
     4    10    16 
     6    12    18 

高温高压

于 2013-04-01T22:51:34.033 回答
2

继上一篇文章中的线程之后,建议不要将您的函数包装在一个类中,而是使用一个类来传递编译后您无法使用的全局变量。

classdef Foo < handle
  properties
    value
  end

  methods
    function obj = Foo(value)
      obj.value = value;
    end
  end
end

注意:类 Foo 扩展handle类以使其通过引用传递,而不是通过值传递。请参阅:句柄和值类之间的比较

function foo = matlabA()
  foo = new Foo(1);
end

function matlabB(foo)
  foo.value
end

据我所知,matlab 编译器不会像这样编译代码,而是将其与 MATLAB 组件运行时的副本一起打包,并编写一些包装函数来处理从 c/c++ 对代码调用所述运行时。

我建议避免过多地在 matlab 和 c/c++ 之间来回跳跃;转换数据类型和调用 MCR 肯定会有一些开销。我真正使用它的只是将一个复杂但自包含的 matlab 脚本(即:不需要在所述脚本的中途与 c/c++ 代码交互)作为一个函数,或者打包代码以部署到环境没有完整的matlab副本。

作为一个有趣的附注:如果您在 Matlab 中调用 C++,并且 C++ 代码需要访问全局变量,事情就容易多了。您可以通过将 C++ 代码包装到mexFunction 中并对其进行编译来简单地做到这一点。在您需要访问 Matlab 工作区中的变量的地方,您可以使用mexGetVariablePtr执行此操作,它将返回指向数据的只读指针。您正在访问的变量可以在全局工作区中,也可以在调用 mexFunction 的函数中。

使用这种方法,我建议对您在 C++ 和 Matlab 代码中获得的变量进行自由注释,因为从 Matlab 方面来看,它们之间的联系可能并不明显;您不希望有人稍后出现,编辑脚本并想知道它为什么会损坏。

在这种情况下,C++ 端似乎不需要访问数据,因此您可以重构它,让 matlab 通过将“获取手指的当前位置”代码包装到 mexFunction 中来进行调用,然后让 matlab 执行环形:

data = loadData();
while(~stop) {
  position = getFingerPositionMex();
  soundByCoef(position, data);
}

假设您不修改soundByCoefMatlab 中的数据将使用按引用传递,因此不会复制大型数据集。

于 2013-04-01T20:02:13.233 回答