АкушерствоАнатомияАнестезиологияВакцинопрофилактикаВалеологияВетеринарияГигиенаЗаболеванияИммунологияКардиологияНеврологияНефрологияОнкологияОториноларингологияОфтальмологияПаразитологияПедиатрияПервая помощьПсихиатрияПульмонологияРеанимацияРевматологияСтоматологияТерапияТоксикологияТравматологияУрологияФармакологияФармацевтикаФизиотерапияФтизиатрияХирургияЭндокринологияЭпидемиология

Void mexFunction(

int nlhs, /* количество выходных параметров */

mxArray *plhs[],/*массив указателей на вых.параметры*/

int nrhs, /* количество входных параметров */

/**/

const mxArray *prhs[]/*массив указ-ей на вход.пар-ры */

);

Отметим, что в английской компьютерной литературе входные и выходные параметры называются "left hand side parameters" (параметры слева от знака присваивания) и "right hand side parameters" (параметры справа от знака присваивания). Сокращения этих названий вошли в имена параметров интерфейсной функции.

Рассмотрим структуру mxArray. Помимо прочих, она содержит следующие поля:

  • имя переменной среды MATLAB в текстовом виде,
  • размерность данной переменной,
  • ее тип,
  • является ли она вещественной или комплексной (в случае комплексной переменной создаются отдельно вектора вещественной и мнимой частей),
  • является ли переменная разреженной матрицей, так как разреженные матрицы имеют отличную от обычных схему хранения данных.

Матрицы (двумерные массивы) являются подмножеством mxArray, для чего в этой структуре предусмотрены поля pr (вещественная часть) и pi (мнимая часть). Каждое из этих полей представляет собой одномерный массив, содержащий элементы матриц (double-числа) поколоночно - сначала все элементы первого столбца матрицы, затем - второго и т.д.

Так как извлечение требуемого типа данных для обработки напрямую из общей структуры может быть сложным (из-за наличия разного рода флажков, типов, размерностей и т.п.), то MATLAB содержит специальную библиотеку вспомогательных функций, облегчающую работу с тем или иным типом данных внутри расширения MATLAB. Все функции этой библиотеки, работающие с массивом mxArray, имеют префикс mx (напр. mxGetPr()).

Другой набор функций в этой же библиотеке имеет префикс mex (напр. mexPrintf()). В отличие от предыдущих, они осуществляют ту или иную операцию в самой среде MATLAB, например - печатают строку текста. Никакая из этих функций не осуществляет прямого доступа к полям mxArray.

Оба указанных набора функций содержатся в динамических библиотеках, находящихся в каталоге \matlab\bin. Эти библиотеки следует подключить к проекту. Не забывайте также включать заголовочный файл mex.h во все исходные файлы вашей программы, в которых используются вызовы функций библиотеки MATLAB или ее типы данных.

В заключение, еще раз подчеркнем, что mxArray в состоянии описать любую переменную MATLAB, что и дает возможность написать расширение, работающее с любым типом данных.

Настройка среды для сборки проекта

Перед началом создания проекта для будущего MEX-файла нужно убедиться в правильности настройки среды (переменных окружения) компилятора, который будет использоваться для компиляции динамической библиотеки.

MATLAB при установке запрашивает тип используемого компилятора и настраивает командные файлы, которые будут компилировать и собирать MEX-файлы при помощи указанного компилятора. Поэтому последовательность, в которой на компьютер устанавливаются компилятор и MATLAB, является довольно важной. Лучше, чтобы сначала на компьютер был установлен компилятор C (Microsoft Visual C++ 5.0), а затем - MATLAB.

В простых случаях, например, когда весь текст будущего расширения MATLAB содержится в единственном файле, имеется возможность вызвать последовательность операций сборки (компиляция, связывание и т.п.) прямо из среды MATLAB - при помощи команды MEX. Указанная команда является обычным batch-файлом Windows, в котором содержатся вызовы компилятора и других необходимых программ. Поэтому ею же можно воспользоваться для сборки расширения и в командной строке MS-DOS.

Для работы в этом режиме нужно, чтобы были правильно настроены переменные среды окружения, необходимые компилятору при работе.

Проверьте следующие установки, вызвав команду set | more в окне MS-DOS:

MSVCDir=d:\program files\devstudio\vc

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

include=%MSVCDir%\include;%MSVCDir%\mfc\include

lib=%MSVCDir%\lib;%MSVCDir%\mfc\lib

path=…(пути к прочим

программам)…;%MSVCDir%\bin;c:\MATLAB\bin

Если что-то не в порядке, надо поправить файл autoexec.bat (или, под Windows NT, изменить значения в "Панель Управления/Система") так, чтобы указанные пути соответствовали реально установленным программам.

После выполнения указанных настроек имеет смысл протестировать всю систему сборки. Для этого нужно скопировать к себе в рабочий каталог файл yprime.c из папки \MATLAB\extern\examples\mex. Затем, в среде MATLAB, сделать рабочий каталог текущим при помощи команды cd.

Скомпилируйте и вызовите тестовую программу. Если переменные среды окружения настроены правильно, то вы должны получить следующий результат:

" mex yprime.c

" yprime(1,1:4)

ans =

2.0000 8.9685 4.0000 -1.0947

Данный пример содержит решение упрощенной задачи трех тел (Земля, Луна и легкий спутник) с координатами в центре масс системы Земля-Луна. Полученные числа являются координатами спутника и компонентами его скорости через одну единицу времени. В каталоге \MATLAB\extern\examples\mex есть файл yprime.m, решающий ту же задачу на языке MATLAB.

Если расширение MATLAB состоит из нескольких исходных текстов, то сборку такого расширения все равно можно выполнить той же командой, например:

" mex circle.c square.obj rectangle.c shapes.lib

В более сложных случаях, когда проект сложный и содержит много исходных текстов, элементы пользовательского интерфейса (ресурсы) и т.п., можно специальным образом настроить проект непосредственно в интегрированной среде Visual C++. Для этого следует выполнить следующие действия:

1.создать проект DLL и добавить в него все необходимые исходные файлы, а также файл mexversion.rc;

2.создать DEF-файл для проекта и явно экспортировать единственную интерфейсную функцию: LIBRARY MYFILE.DLL EXPORTS mexFunction

3.включить созданный.DEF-файл в проект;

4.создать библиотеку импорта для MEX-функций из файла MATLAB.DEF, находящегося в каталоге \MATLAB\extern\include: LIB /DEF:MATLAB\EXTERN\INCLUDE\MATLAB.DEF/OUT:mymeximports.lib

5.добавить эту библиотеку в проект;

6.добавить каталог \MATLAB\EXTERN\INCLUDE к другим include-каталогам в опциях препроцессора для проекта (Project/Settings/Preprocessor);

7.на этой же вкладке добавить MATLAB_MEX_FILE к списку предопределенных символов (Preprocessor definitions) для всех конфигураций (Release/Debug) проекта;

8.для отладки можно во вкладке Debug (Project/Settings/Debug) указать в качестве запускающей программы (Executable for debug session) для проекта саму программу MATLAB: \MATLAB\BIN\MATLAB.EXE. Тогда можно будет задавать точки остановки внутри вашего расширения MATLAB, просматривать значения его переменных, проходить его в пошаговом режиме и выполнять другие отладочные действия.

Схема взаимодействия MATLAB и MEX-файла

Пусть в среде MATLAB производится вызов функции из MEX-файла:

[C,D]=fun(A,B);

После этого MATLAB создает четыре структуры типа mxArray: A, B, C, D. Структуры A и B будут содержать указатели на данные соответствующих матриц, а структуры C и D будут пока пустыми:

const mxArray *A;
A = prhs[0]

const mxArray *B;
B = prhs[1]

Внутри интерфейсной функции MEX-файла можно воспользоваться вспомогательной функцией mxGet___() для получения указателей на данные. Естественно, следует выбрать функцию mxGet___() соответствующую полю структуры mxArray, которое требуется считать.

Полученные указатели на данные следует передать в вычислительную функцию, которая и должна произвести все необходимые действия для получения результата. Не стоит перегружать интерфейсную функцию реальными вычислениями - это ухудшит читаемость разрабатываемой программы и затруднит ее отладку.

В ходе вычислений почти наверняка придется выделять память для хранения вспомогательных и результирующих данных.

Для этого лучше всего воспользоваться функцией mxCreate__(), соответствующей типу данных, под которые надо выделить память. Использование этой функции гарантирует, что MATLAB сможет корректно уничтожить переменную, созданную внутри MEX-файла, если это потребуется. Если память выделяется обычным образом, при помощи оператора new или функции malloc(), то можно воспользоваться функцией mxSet__() для упрощения присваивания значений полям структуры mxArray. Для того, чтобы возвратить выходные параметры C и D обратно в среду MATLAB, следует проинициализировать массив выходных параметров:

mxArray *C;
C = prhs[0];

mxArray *D;
D = prhs[1];

Далее, указатели C и D можно использовать для присваивания конкретных значений.

После возвращения управления в среду MATLAB полученные переменные C и D можно будет использовать обычным образом.

Пример программы

Ниже приводится текст законченного примера расширения среды MATLAB, в котором производится удвоение переданного аргумента.

#include "mex.h"
#include <math.h>

/* Вычислительная процедура */
void timestwo(double y[], double x[])

{

y[0] = 2.0*x[0];
return;

}

/* Интерфейсная функция */
void mexFunction(

int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])

{

double *y;
double *x;
unsigned int m, n;

/* Проверяем количество аргументов. */
if (nrhs!=1) {
mexErrMsgTxt("Only one input argument
allowed.");}

else if (nlhs!=1) {
mexErrMsgTxt("Only one output argument
allowed.");

}

/* Входной аргумент x должен быть скаляром. */
m = mxGetM(prhs[0]);
n = mxGetN(prhs[0]);
if (!mxIsDouble(prhs[0] || mxIsComplex(prhs[0])
||!(m ==1 && n ==1)){
mexErrMsgTxt("Input x must be a scalar."); }

/* Создаем выходную матрицу для возврата в среду MATLAB. */
plhs[0] = mxCreateDoubleMatrix(m, n, mxREAL);

/*Инициализир. указатели на вход. и вых.пар-тры. */
y = mxGetPr(plhs[0]);
x = mxGetPr(prhs[0]);

/* Вызываем вычислительную функцию. */
timestwo(y, x); }

/* Конец файла.*/

Вызов команд среды MATLAB из MEX-файла

Есть возможность вызывать функции, операторы, M-файлы и даже другие MEX-файлы в среде MATLAB прямо из вашего MATLAB-расширения, написанного на языке C. Для этого нужно воспользоваться функцией из библиотеки MATLAB mexCallMATLAB(). Использование ее аналогично другим mx__() и mex__() функциям.

Следующий пример создает заполненный массив, вызывает функцию mexCallMATLAB() для показа его содержимого, затем, через нее же вычисляет собственные вектора и собственные значения заданной матрицы в среде MATLAB, и, наконец в третий раз вызывает эту же функцию для показа собственных векторов.

#include "mex.h"

#include<math.h>

void mexFunction(int nlhs,mxArray *plhs[],

int nrhs,const mxArray *prhs[])

{

double pr[] = {5.2, 7.9, 1.3, 4.2};
double pi[] = {3.4, 6.5, 2.2, 9.1};
mxArray *array_ptr; int num_out, num_in;
mxArray *output_array[2], *input_array[2];

/* Создаем заполненную матрицу размерности 2х2.*/
array_ptr = mxCreateDoubleMatrix(2, 2, mxCOMPLEX);
memcpy(mxGetPr(array_ptr), pr, 4*sizeof(double));
memcpy(mxGetPi(array_ptr), pi, 4*sizeof(double));

/* В среде MATLAB это эквивалентно disp(array). */
num_out = 0;
num_in = 1;
input_array[0] = array_ptr;
mexCallMATLAB(num_out, output_array,
num_in, input_array, "disp");

/* А это - то же самое, что [v, d] = eig(array). */
num_out = 2;
num_in = 1;
input_array[0] = array_ptr;
mexCallMATLAB(num_out, output_array,
num_in, input_array, "eig");

/* Выведем результат: disp(v). */
num_out = 0;
num_in = 1;
input_array[0] = output_array[0];
mexCallMATLAB(num_out, output_array,
num_in, input_array, "disp"); }

/* Конец файла.*/

Отметим, что функцией mexCallMATLAB() можно пользоваться вперемешку с собственными вычислениями в расширении MATLAB, так же, как и остальными функциями библиотек MATLAB.

Задания

1.Изучить примеры, расположенные в каталоге \matlab\extern\examples.

2.Настроить свой компьютер так, чтобы при помощи команды mex из среды MATLAB можно было скомпилировать и протестировать предложенный пример, удваивающий свой аргумент.

3.В среде Microsoft Visual C++ создать проект расширения MATLAB для подсчета произведения матриц любого размера. Для матриц достаточно большого размера сравнить производительность созданного расширения с производительностью оператора произведения матриц в среде MATLAB.

4.Написать расширение MATLAB для решения произвольных систем линейных уравнений методом исключения Гаусса и сравнить его производительность с производительностью соответствующего оператора MATLAB.

5.Написать расширение MATLAB для вычисления и отображения в среде MATLAB последовательности простых чисел заданной длины.


#$+Вызов из MatLab'а кода, написанного на C/C++.


Дата добавления: 2015-01-18 | Просмотры: 781 | Нарушение авторских прав



1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |



При использовании материала ссылка на сайт medlec.org обязательна! (0.009 сек.)