在Visual Studio中直接调用MATLAB(多线程)

时间:2014-10-05 03:31:59

标签: c++ multithreading visual-studio matlab mixed-programming

目前我正在尝试直接在Visual Studio中调用MATLAB,但它似乎无法正常工作。

为清楚起见,以下面的演示案例为例,即使用MATLAB计算2+3。预计结果即ans = 5应打印在行printf("%s\n", buf);中,结果为空。顺便说一下,MATLAB引擎已成功打开(engOpen())。

#include <stdio.h>
#include <thread>
#include "engine.h"

Engine *matlab;

void thread_func()
{
    // set printing buffer
    char buf[1001]; 
    engOutputBuffer(matlab, buf, 1000);

    // call MATLAB
    engEvalString(matlab, "2+3");
    printf("%s\n", buf); // if ok, should print "ans = 5" in the command window
}

int main()
{
    // Open MATLAB engine
    matlab = engOpen(NULL);
    if (matlab == NULL){
        printf("Error to open MATLAB engine!!!\n");
        exit(-1);
    }

    // use "Engine *matlab" in this thread
    std::thread another_thread(thread_func);

    // wait the thread to finish
    another_thread.join();

    // Close MATLAB engine
    engClose(matlab);

    return 0;
}

更多信息:

  • MATLAB版本:R2014a x64
  • Visual Studio版本:2013专业版
  • 项目的构建平台也设置为x64。
  • 在运行代码时创建MATLAB命令窗口,这是预期的。

2 个答案:

答案 0 :(得分:1)

对于Visual Studio 2010。

如果您使用的是Matlab 64,则需要将Visual Studio配置为64位。

第一步:

包括engine.h

C/C++->General->Additional Include Directories

添加C:\Program Files\MATLAB\R2014a\extern\include

第二步:

Linker->General->Additional Library Directories

添加C:\Program Files\MATLAB\R2014a\extern\lib\win64\microsoft

第三步:

在环境变量中添加C:\Program Files\MATLAB\R2014a\bin\win64

代码的输出是

enter image description here

答案 1 :(得分:1)

这是我尝试的一个简单示例:

test_engine.cpp

#include <cstdio>
#include "engine.h"

#define BUFSIZE 1000

int main()
{
    // open connection
    Engine *matlab = engOpen(NULL);
    if (matlab == NULL) {
        fprintf(stderr, "Error to open MATLAB engine\n");
        return EXIT_FAILURE;
    }

    // output buffer
    char buf[BUFSIZE+1];
    buf[BUFSIZE] = '\0';
    engOutputBuffer(matlab, buf, BUFSIZE);

    // call MATLAB
    engEvalString(matlab, "x = magic(5)");

    printf("Output:\n%s\n", buf);

    // close connection
    engClose(matlab);

    return EXIT_SUCCESS;
}

而不是手动创建Visual Studio项目来编译它,we can do this直接来自MATLAB:

>> mbuild test_engine.cpp -llibeng -llibmx

在R2014a及以上,我们也可以使用:

>> mex -client engine test_engine.cpp

(假设您已经运行mex -setupmbuild -setup来选择正确的C ++编译器,或者在R2014a中选择mex -setup C++mex -setup C++ -client MBUILD

这是程序的输出(我用VS2013运行R2014a x64):

C:\> test_engine.exe
Output:
x =
    17    24     1     8    15
    23     5     7    14    16
     4     6    13    20    22
    10    12    19    21     3
    11    18    25     2     9

编辑:

这是how to在Visual Studio中编译上面的例子。

  1. 首先创建一个新的空“Win32控制台应用程序”项目

  2. 由于我们正在使用MATLAB x64,我们需要调整项目配置以生成64位二进制文​​件。从“Build”菜单中,选择“Configuration Manager”。从下拉菜单中选择<New>以创建新的平台配置,选择x64并接受。

  3. 添加上一个示例test_engine.cpp

  4. 中的源代码
  5. 下一步是告诉VC ++编译器/链接器在哪里找到MATLAB头文件和库。我们可以通过设置项目属性来完成此任务。

    更好的方法是创建一个单独的property sheet,可以从多个项目中重复使用,而无需一遍又一遍地重复相同的设置。因此,创建如下所示的MATLAB_Engine.props属性表,并将其添加到项目中(打开“Property Manager”面板,然后单击“添加现有属性表”按钮)。

  6. 最后构建解决方案并运行它( Ctrl + F5

  7. MATLAB_Engine.props

    <?xml version="1.0" encoding="utf-8"?>
    <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <ImportGroup Label="PropertySheets" />
      <PropertyGroup Label="UserMacros" />
      <PropertyGroup>
        <LocalDebuggerEnvironment>PATH=C:\Program Files\MATLAB\R2014a\bin\win64;%PATH%$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
      </PropertyGroup>
      <ItemDefinitionGroup>
        <ClCompile>
          <AdditionalIncludeDirectories>C:\Program Files\MATLAB\R2014a\extern\include;C:\Program Files\MATLAB\R2014a\extern\include\win64</AdditionalIncludeDirectories>
          <PreprocessorDefinitions>IBMPC</PreprocessorDefinitions>
        </ClCompile>
        <Link>
          <AdditionalLibraryDirectories>C:\Program Files\MATLAB\R2014a\extern\lib\win64\microsoft</AdditionalLibraryDirectories>
          <AdditionalDependencies>libmx.lib;libmex.lib;libmat.lib;libeng.lib;mclmcrrt.lib</AdditionalDependencies>
        </Link>
      </ItemDefinitionGroup>
      <ItemGroup />
    </Project>
    

    (适用于64位Windows上的MATLAB R2014a。如果将MATLAB安装到其他位置,请调整路径)

    预期输出:

    output

    提示:如果您反复测试引擎程序,那么每次运行新的MATLAB进程都会在后台打开和关闭。为了在开发过程中简化操作,您可以启动一个正常的MATLAB会话,并执行下面的命令,告诉它像自动化服务器一样。这样,所有引擎程序都将在同一会话中运行,该会话仍保持打开状态。

    >> enableservice('AutomationServer',true);
    

    EDIT2:

    MATLAB documentation明确指出Engine库不是thread-safe(对于MEX-API和MAT-API也是如此)。在Windows系统中,独立Engine程序通过COM接口与外部MATLAB进程通信,而在Linux / Mac系统上使用pipes作为IPC机制。

    因此,如果您创建多线程应用程序,请确保只有一个线程访问引擎应用程序。

    注意:仅适用于Windows,还有另一个功能engOpenSingleUse。它与engOpen的不同之处在于它创建了一个新的非共享MATLAB引擎会话。这样,您可以将多个线程连接到不同的会话(显然工作空间不共享,因为每个会话都有一个单独的地址空间)。