【问题标题】:Call MATLAB directly (multiple threading) in Visual Studio在 Visual Studio 中直接调用 MATLAB(多线程)
【发布时间】:2014-10-05 03:31:59
【问题描述】:

目前我正在尝试在 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 命令窗口在运行代码时创建,这是预期的。

【问题讨论】:

  • 你遇到了什么错误?
  • @CroCo 正如我在问题中所说,没有错误,但我无法获得预期的输出/结果。
  • 输出是什么?它只是一个空的黑屏吗?
  • 在您运行代码时是否正在运行 Matlab?
  • @CroCo 是的,新的 MATLAB 将在运行代码时创建。

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


【解决方案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 位二进制文​​件。从“构建”菜单中,选择“配置管理器”。从下拉菜单中选择&lt;New&gt; 以创建新的平台配置,选择x64 并接受。

  3. 添加上一个示例的源代码test_engine.cpp

  4. 下一步是告诉 VC++ 编译器/链接器在哪里可以找到 MATLAB 头文件和库。我们可以通过设置项目属性来做到这一点。

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

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

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 安装到其他位置,请调整路径)

预期的输出:

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

>> enableservice('AutomationServer',true);

编辑2:

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

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

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

【讨论】:

  • 嗨,Amro,谢谢。其实我可以重现你说的。但是,我仍然不能让它在 VC 项目中工作。有什么想法吗?
  • @herohuyongtao:应该没有什么不同。请参阅我的编辑以获取说明。
  • 您好 Amro,感谢您耐心的帮助。 +1 对您非常鼓舞人心的回答,尤其是对于最后一个 tip,这非常有用。仅供参考,我终于在我的案例中找到了真正的问题,即尝试在一个线程中创建 MATLAB 引擎并在另一个线程中使用它,请参阅my own answer。再次感谢。
  • @herohuyongtao:啊,你从来没有提到多线程!我又做了一次修改。
【解决方案2】:

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

你的代码的输出是

【讨论】:

  • 嗨 CroCo,仅供参考,我终于找到了我的情况的真正问题,即尝试在一个线程中创建 MATLAB 引擎并在另一个线程中使用它,请参阅my own answer。此外,对您的回答 +1,它实际上以单线程样式工作。再次感谢。
  • 那么您需要编辑您的问题,使其反映多线程问题。
猜你喜欢
  • 2017-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-31
  • 1970-01-01
  • 2015-11-10
  • 2019-01-28
相关资源
最近更新 更多