1

目前我正在尝试直接在 Visual Studio 中调用 MATLAB,但它似乎不起作用。

为了清楚起见,以下面的演示案例为例,即使用 MATLAB 计算2+3. 预计结果 ieans = 5应打印在 lineprintf("%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 命令窗口,这是预期的。
4

2 回答 2

1

Here is a simple example I tried:

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

Instead of manually creating a Visual Studio project to compile it, we can do this right from MATLAB:

>> mbuild test_engine.cpp -llibeng -llibmx

in R2014a and up, we can also use:

>> mex -client engine test_engine.cpp

(assuming you've run mex -setup and mbuild -setup to select a proper C++ compiler, or mex -setup C++ and mex -setup C++ -client MBUILD in R2014a).

Here is the output of the program (I'm running R2014a x64 with VS2013):

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

EDIT:

Here is how to compile the above example in Visual Studio.

  1. Start by creating a new empty "Win32 Console Application" project

  2. Since we're working with MATLAB x64, we need to adjust project configuration to generate 64-bit binaries. From "Build" menu, select "Configuration Manager". From the drop-down menu choose <New> to create a new platform configs, select x64 and accept.

  3. Add the source code from the previous example test_engine.cpp

  4. Next step is tell the VC++ compiler/linker where to find MATLAB headers and libraries. We could do this by setting the project properties.

    A better approach is to create a separate property sheet that can be reused from multiple projects without having to repeat the same settings over and over again. So create the MATLAB_Engine.props property sheet shown below, and add it the project (open the "Property Manager" panel and click the "Add Existing Property Sheet" button).

  5. Finally build the solution and run it (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>

(this is intended for MATLAB R2014a on a 64-bit Windows. Adjust the path if you installed MATLAB to a different location)

The output as expected:

output

Tip: if you are testing an engine program repeatedly, then each time it runs a new MATLAB process opens up and closes in the background. To make things easier during development, you could start a normal MATLAB session, and execute the command below to tell it to act like as an Automation server. That way all Engine programs will run in this same session which remains open.

>> enableservice('AutomationServer',true);

EDIT2:

The MATLAB documentation explicitly states that the Engine library is not thread-safe (same goes for the MEX-API and the MAT-API). In Windows systems, standalone Engine programs communicate with the external MATLAB process through a COM interface, while it uses pipes on Linux/Mac systems as IPC mechanism.

So if you create multi-threaded applications, make sure only one thread accesses the engine application.

Note: For Windows only, there is another function engOpenSingleUse. It differs from engOpen in that it creates a new non-shared MATLAB engine session. That way you can have multiple threads each connected to a different session (obviously workspace is not shared, because each session has a separate address space).

于 2014-10-05T18:47:43.083 回答
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环境变量。

您的代码的输出是

在此处输入图像描述

于 2014-10-05T05:09:15.990 回答