Данные MATLAB в S-функциях C

MATLAB® данные представлены как mxArrays на языке C/C + +. The mxArray структура обычно содержит тип, размерность, данные, тип данных, разреженность, а также номера полей и полей массива MATLAB. В S-функциях Передайте параметры диалога в S-функции значения, оцененные в MATLAB, передаются в Simulink® как mxArray. Список функций см. в API C Matrix.

S-функции считывают данные MATLAB в основном для следующих целей:

  • Доступ к параметрам диалогового окна блоков с помощью mxArrays

  • Передайте аргументы в или из функции MATLAB с помощью mexCallMATLAB

mxArray Манипуляция

Можно манипулировать mxArrays в S-функциях с использованием стандартных функций MATLAB API. В целом, если ваша S-функция объявлена свободной исключением путем передачи SS_OPTION_EXCEPTION_FREE_CODE опция для ssSetOptions (см. Исключение Free Code в Handle Errors in S-Functions), он должен избегать функций MATLAB API, которые выдают исключения (то есть, скачок в длину), таких как mxCreateDoubleMatrix. В противном случае S-функция может использовать любую из перечисленных функций.

Примечание

Параметры S-функции доступны только для чтения в алгоритме S-функции. Вы можете изменить значения параметров в диалоговом окне Блока s-function или маске.

Если у вас есть Simulink Coder™, он поддерживает подмножество mxArray функции манипуляции при генерации неинстрированного кода для S-функции. Список поддерживаемых функций см. в Write Noninlined S-Function (Simulink Coder).

Вызовы макроса ssGetSFcnParam возвращает указатель на mxArray, который можно использовать с mxArray функции манипуляции. Если ваша S-функция содержит параметры S-функции, используйте mxArray функции манипуляции в mdlCheckParameters метод для проверки значений параметров S-функции. Смотрите S-функцию sfun_runtime3.c для примера

В этой S-функции следующие линии проверяют, что первый параметр S-функции является символьным массивом с длиной, большей или равной двум.

if (!mxIsChar(ssGetSFcnParam(S, 0)) ||
     (nu=mxGetNumberOfElements(ssGetSFcnParam(S, 0))) < 2) {
     ssSetErrorStatus(S,"1st parameter to S-function must be a "
       "string of at least 2 '+' and '-' characters");
     return;
}

mxArrays Использование 32-битных API

Чтобы написать программы на C/C + +, которые работают с MATLAB mxArray структура данных, используйте матричные API на C. Матричные API на C поддерживают 32-разрядную и 64-разрядную индексацию. По умолчанию ваши S-функции создаются с использованием 32-битных API. Проверьте Upgrade MEX Files, чтобы использовать 64-Bit API, чтобы увидеть, как обновить существующие файлы MEX.

Чтобы проверить использование 32-битных API, можно запустить советник по обновлению S-функций. На вкладке Modeling выберите Model Advisor > Upgrade Advisor.

Если вы создаете свой код с -largeArrayDims и ваш код заполняет ssParamRec размерность структуры с mxArray размерности, начиная R2018a, вы больше не можете приводить возврат значение mxGetDimensions в int_T pointer потому что mxGetDimensions теперь возвращает size_T указатель на 64-разрядных платформах. В качестве обходного пути создайте временную копию типа int_T и присвоить его dims область ssParamRec структура.

Замените:С:
ssParamRec p;
p.dims = (int_T *) mxGetDimensions(ssGetSFcnParam(S, 0));
// Set up other fields of p
if (!ssSetRunTimeParamInfo(S, 0, &p)) {
       free(dims);
       return;
}
free(dims); // free memory allocated for dimensions
ssParamRec p;
const mxArray* mxPrm = ssGetSFcnParam(S, 0);
const mwSize* mxDims = mxGetDimensions(mxPrm);
const mwSize mxNumDims = mxGetNumberOfDimensions(mxPrm);
mwSize idx;
int_T * dims = malloc(sizeof(int)*mxNumDims);
for (idx=0; idx < mxNumDims; idx++)
{
   dims[idx] = mxDims[idx];
} 

p.dims = dims;
// Set up other fields of p

if (!ssSetRunTimeParamInfo(S, 0, &p)) {
       free(dims);
       return;
}
free(dims); // free memory allocated for dimensions

mxArrays Использование чередующегося комплексного представления

До версии MATLAB 9.4 (R2018a), mxArrays использовали отдельное комплексное представление, где действительная и мнимая части комплексного числа хранились отдельно. Начиная с версии 9.4 (R2018a), MATLAB использует чередующееся представление для хранения комплексных данных, где действительная и мнимая части комплексных чисел хранятся вместе. Для S-функций, чтобы манипулировать mxArrays, больше не нужно преобразовывать данные из отдельного в перемеженный комплекс. Смотрите Поддержку MATLAB для Interleaved Complex API в MEX-функции для получения дополнительной информации о том, как обновить ваш код.

Примечание

Чтобы хранить комплексные данные для входных и выходных сигналов или DWorks, Simulink использует чередующееся представление.

Чтобы автоматически проверить свои S-функции на потенциальные проблемы перемеженных комплексных данных, на вкладке Modeling, выберите Model Advisor > Upgrade Advisor. В окне Upgrade Advisor выберите Check model for S-function upgrade issues.

Следующая выборка кода копирует значение параметров из mxArray на выход S-функции. В этом примере размерности, тип данных и сложность параметра и выходного аргумента гарантируются одинаковыми. Для примера, если параметр комплексен, выход сигнал комплексен. Если параметр вещественный, выходной сигнал действителен. Для примера ниже, тип данных и параметра, и выхода является double (real_T). До R2018a можно было использовать mxGetPr и mxGetPr копировать действительные и мнимые части комплексных данных отдельно. С перемеженным комплексным представлением можно использовать memcpy, которая является инструкцией единственного экземпляра.

Замените:С:
    real_T            *y     = ssGetOutputPortRealSignal(S,0);
    boolean_T   yIsComplex = ssGetOutputPortComplexSignal(S, 0) == COMPLEX_YES;
    int_T             yWidth = ssGetOutputPortWidth(S,0);

    const real_T      *pr    = mxGetPr(ssGetSFcnParam(S, 0));          
    const real_T      *pi    = mxGetPi(ssGetSFcnParam(S, 0));

   int               i;

    for (i = 0; i < yWidth; i++) {

        int_T idx = (yIsComplex)  ? 2*i : i;
        y[idx] =  pr[idx];

        if(yIsComplex){
             y[idx+1] = pi[idx];
        }
    }
    real_T            *y     = ssGetOutputPortRealSignal(S,0);
    boolean_T   yIsComplex = ssGetOutputPortComplexSignal(S, 0) == COMPLEX_YES;
    int_T             yWidth = ssGetOutputPortWidth(S,0);

    mxComplexDouble *pc;
    mxDouble *pr;

   if (yIsComplex) {

        pc = mxGetComplexDoubles(ssGetSFcnParam(S, 0));
        memcpy(y, pc, yWidth*sizeof(mxComplexDouble));

   } else {

       pr = mxGetDoubles(ssGetSFcnParam(S, 0));
       memcpy(y, pr, yWidth*sizeof(mxDouble)); 

   }
[a]

[a] 

sizeof(mxComplexDouble)=2*sizeof(mxDouble)=2*sizeof(real_T)

См. также

|

Похожие темы