首页 文章

如何将Matlab类编译成C lib?

提问于
浏览
4

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

我'm trying to encapsulate the 2411006 into an object. However I don'知道如何使用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

生成的lib实际上是独立的函数而不是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(),它在主循环中完成工作 .

2 回答

  • 6

    正如Alan所指出的,I was仅建议使用句柄类作为全局变量的容器(这样的对象将通过引用传递) . 创建的对象不是由C代码直接操作的(它将存储在通用的 mxArray/mwArray C / C结构中) .

    As far as I know,在使用MATLAB编译器构建共享库时,无法直接将classdef样式的MATLAB类编译为适当的C类 . 它只支持构建常规功能 . 您可以为MATLAB类成员方法创建功能接口,但这是一个不同的故事......

    也许一个完整的例子可以帮助说明我的想法 . 首先让我们在MATLAB端定义代码:

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

    MATLAB函数作为C函数公开

    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程序来测试库:

    main.cpp

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

    HTH

  • 2

    previous post中的线程之后,建议不是将函数包装在类中,而是使用类来传递编译使您无法使用的全局变量 .

    classdef Foo < handle
      properties
        value
      end
    
      methods
        function obj = Foo(value)
          obj.value = value;
        end
      end
    end
    

    注意:类Foo扩展 handle 类以使其通过引用传递,而不是按值传递 . 见:the comparison between handle and value classes .

    function foo = matlabA()
      foo = new Foo(1);
    end
    
    function matlabB(foo)
      foo.value
    end
    

    据我所知,matlab编译器不会编译代码,而是packages it with a copy of the MATLAB Component Runtime并编写一些包装器函数来处理从c / c代码调用所述运行时 .

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

    As an interesting side note: if you are calling C++ from within Matlab ,并且C代码需要访问全局变量,事情要容易得多 . 您可以通过将C代码包装到mexFunction并编译它来完成此操作 . 在您需要访问Matlab工作空间中的变量的位置,您可以使用mexGetVariablePtr来执行此操作,它将返回指向数据的只读指针 . 您正在访问的变量可以位于全局工作空间中,也可以位于调用mexFunction的函数中 .

    通过这种方法,我建议自由地评论你在C和Matlab代码中得到的变量,因为它们之间的链接在Matlab方面可能并不明显;你不希望别人后来出现,编辑脚本并想知道它为什么会坏掉 .

    In this case it seems that the C++ side doesn't really need access to the data ,所以你可以重构它让matlab通过将"get current position of fingers"代码包装到mexFunction来进行调用,然后让matlab做循环:

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

    假设您没有修改 soundByCoef 中的数据,Matlab将使用传递引用,因此不会复制大型数据集 .

相关问题