Вызов MATLAB напрямую (многопоточность) в Visual Studio

В настоящее время я пытаюсь вызвать MATLAB непосредственно в Visual Studio, но, похоже, он не работает.

Для ясности возьмем в качестве примера следующий демонстрационный пример, т.е. используйте 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 Professional
  • Платформа сборки проекта также установлена ​​на x64.
  • Командное окно MATLAB создается во время выполнения кода, что и ожидается.

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 для его компиляции, мы можем это сделать прямо из MATLAB:

>> mbuild test_engine.cpp -llibeng -llibmx

в R2014a и выше мы также можем использовать:

>> mex -client engine test_engine.cpp

(при условии, что вы бежали mex -setup а также mbuild -setup выбрать правильный компилятор C ++, или mex -setup C++ а также mex -setup C++ -client MBUILD в R2014a).

Вот вывод программы (я использую R2014a x64 с 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

Вот как скомпилируйте приведенный выше пример в Visual Studio.

  1. Начните с создания нового пустого проекта «Win32 Console Application»

  2. Поскольку мы работаем с MATLAB x64, нам нужно настроить конфигурацию проекта для генерации 64-битных двоичных файлов. В меню «Сборка» выберите «Диспетчер конфигурации». Из выпадающего меню выберите <New> для создания новой конфигурации платформы выберите x64 и принять.

  3. Добавьте исходный код из предыдущего примера test_engine.cpp

  4. Следующий шаг — сообщить компилятору / компоновщику VC ++, где найти заголовки и библиотеки MATLAB. Мы могли бы сделать это, установив свойства проекта.

    Лучше всего создать отдельный лист недвижимости это может быть повторно использовано из нескольких проектов без необходимости повторять одни и те же настройки снова и снова. Так что создайте 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>

(это предназначено для MATLAB R2014a в 64-битной Windows. Настройте путь, если вы установили MATLAB в другое место)

Выход, как и ожидалось:

выход

Совет: если вы тестируете программу движка несколько раз, то каждый раз при запуске новый процесс MATLAB открывается и закрывается в фоновом режиме. Чтобы упростить процесс разработки, вы можете запустить обычный сеанс MATLAB и выполнить приведенную ниже команду, чтобы он действовал как сервер автоматизации. Таким образом, все программы Engine будут работать в том же сеансе, который остается открытым.

>> enableservice('AutomationServer',true);

MATLAB документация прямо заявляет, что библиотека Engine не потокобезопасной (то же самое касается MEX-API и MAT-API). В системах Windows, автономный двигатель программы взаимодействуют с внешним процессом MATLAB через COM интерфейс, в то время как он использует трубы в системах Linux / Mac как IPC механизм.

Поэтому, если вы создаете многопоточные приложения, убедитесь, что только один поток обращается к приложению движка.

Примечание: только для Windows, есть другая функция engOpenSingleUse, Отличается от engOpen в том смысле, что он создает новый сеанс ядра MATLAB без общего доступа. Таким образом, вы можете иметь несколько потоков, каждый из которых подключен к отдельному сеансу (очевидно, что рабочее пространство не используется совместно, поскольку каждый сеанс имеет отдельное адресное пространство).

1

Другие решения

Для Visual Studio 2010.

Если вы используете Matlab 64, вам нужно настроить 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 в переменных среды.

Вывод вашего кода

введите описание изображения здесь

1

По вопросам рекламы [email protected]