Из кода MATLAB ® можно напрямую вызвать внешний код C/C + +, также называемый пользовательским кодом или устаревшим кодом. Для вызова функций C/C + + используйтеcoder.ceval. Генератор кода интегрирует код C/C + + в код C/C + +, сгенерированный из MATLAB. Интегрируйте код при наличии внешних библиотек, оптимизированного кода или файлов объектов, разработанных в C/C + +, которые необходимо использовать с созданным кодом. Если внешний код использует типы переменных, которые не определены или не распознаны MATLAB, используйтеcoder.opaque функция в сочетании с coder.ceval. Чтобы зарезервировать определенные имена идентификаторов для использования в пользовательском коде C/C + +, который требуется интегрировать с сгенерированным кодом, используйте coder.reservedName функция.
Ниже приведены некоторые основные рабочие процессы для интеграции внешнего кода. Дополнительные примеры см. в разделе coder.ceval справочная страница.
Примечание
С помощью coder.ceval, вы получаете неограниченный доступ к внешнему коду. Неправильное использование этих функций или ошибки в коде могут дестабилизировать MATLAB и привести к его остановке. Для отладки кода и анализа сообщений об ошибках при компиляции просмотрите вкладку Журналы построения в отчете о создании кода.
В этом примере показано, как интегрировать простую функцию C с кодом MATLAB ® с помощью coder.ceval. Рассмотрим функцию MATLAB, mathOps:
function [added, multed] = mathOps(in1, in2) added = in1+in2; multed = in1*in2; end
В этом примере предположим, что требуется реализовать операцию добавления с помощью внешнего кода C. Рассмотрим функцию C, adder, реализовано в файле adder.c:
#include <stdio.h>
#include <stdlib.h>
#include "adder.h"
double adder(double in1, double in2)
{
return in1 + in2;
}
Объединяться adder с кодом MATLAB необходим файл заголовка, содержащий прототип функции. Просмотр файла adder.h:
double adder(double in1, double in2);
Используйте coder.ceval для вызова функции C в mathOpsIntegrated.m. Включить файл заголовка с помощью coder.cinclude.
function [added, multed] = mathOpsIntegrated(in1, in2) %#codegen % for code generation, preinitialize the output variable % data type, size, and complexity added = 0; % generate an include in the C code coder.cinclude('adder.h'); % evaluate the C function added = coder.ceval('adder', in1, in2); multed = in1*in2; end
Для создания кода используйте codegen команда. Укажите исходный файл adder.c в качестве входных данных. Для тестирования кода C выполните функцию MEX и проверьте результаты вывода.
codegen mathOpsIntegrated -args {1, 2} adder.c [test1, test2] = mathOpsIntegrated_mex(10, 20)
Code generation successful.
test1 =
30
test2 =
200
Язык C ограничивает функции от возврата нескольких выходов. Вместо этого они возвращают только одно скалярное значение. Функции MATLAB coder.ref, coder.rref и coder.wref позволяет вернуть несколько выходов из внешней функции C/C + +.
Например, предположим, что вы пишете функцию MATLAB foo который принимает два входа x и y и возвращает три выходных сигнала a, b, и c. В MATLAB эта функция вызывается следующим образом:
[a,b,c] = foo(x,y)
Если переписать foo функция C не может возвращать три отдельных значения a, b, и c через return заявление. Вместо этого создайте функцию C с несколькими аргументами типа указателя и передайте выходные параметры по ссылке. Например:
void foo(double x,double y,double *a,double *b,double *c)
Затем можно вызвать функцию C из функции MATLAB с помощью coder.ceval функция.
coder.ceval('foo',x,y,coder.ref(a),coder.ref(b),coder.ref(c));Если внешняя функция C выполняет запись только в память или только считывает из памяти, передаваемой по ссылке, можно использовать coder.wref или coder.rref функции вместо coder.ref. При определенных обстоятельствах эти функции могут обеспечить дальнейшую оптимизацию сгенерированного кода. При использовании coder.wref(arg) пройти arg по ссылке, ваша внешняя функция C/C + + должна полностью инициализировать память, на которую ссылается arg.
В этом примере показано, как передавать данные по ссылке на внешнюю функцию C и из нее.
Передача по ссылке является важным методом интеграции кода C/C + +. При передаче данных по ссылке программе не требуется копировать данные из одной функции в другую. При значении pass by код C может возвращать только одну скалярную переменную. При передаче по ссылке код C может возвращать несколько переменных, включая массивы.
Рассмотрим функцию MATLAB adderRef. Эта функция использует внешний код C для добавления двух массивов. coder.rref и coder.wref команды предписывают генератору кода передавать указатели массивам, а не копировать их.
function out = adderRef(in1, in2) %#codegen out = zeros(size(in1)); % the input numel(in1) is converted to integer type % to match the cAdd function signature coder.ceval('cAdd', coder.rref(in1), coder.rref(in2), coder.wref(out), int32(numel(in1)) ); end
Код C, cAdd.c, использует линейное индексирование для доступа к элементам массивов:
#include <stdio.h>
#include <stdlib.h>
#include "cAdd.h"
void cAdd(const double* in1, const double* in2, double* out, int numel)
{
int i;
for (i=0; i<numel; i++) {
out[i] = in1[i] + in2[i];
}
}
Для создания кода C необходимо предоставить файл заголовка, cAdd.h, с подписью функции:
void cAdd(const double* in1, const double* in2, double* out, int numel);
Проверьте код C путем генерации функции MEX и сравнения ее выходных данных с выходными данными операции сложения в MATLAB.
A = rand(2,2)+1; B = rand(2,2)+10; codegen adderRef -args {A, B} cAdd.c cAdd.h -report if (adderRef_mex(A,B) - (A+B) == 0) fprintf(['\n' 'adderRef was successful.']); end
Code generation successful: To view the report, open('codegen/mex/adderRef/html/report.mldatx').
adderRef was successful.В этом примере показано, как вызвать функцию C, использующую типы данных, которые не определены в MATLAB ®.
Например, если код C выполняет ввод или вывод файла типа C 'FILE *', в MATLAB нет соответствующего типа. Для взаимодействия с этим типом данных в коде MATLAB необходимо инициализировать его с помощью функции. coder.opaque. В случае типов структуры можно использовать coder.cstructname.
Например, рассмотрим функцию MATLAB. addCTypes.m. Эта функция использует coder.ceval с типами ввода, определенными во внешнем коде. Функция coder.opaque инициализирует тип в MATLAB.
function [out] = addCTypes(a,b) %#codegen % generate include statements for header files coder.cinclude('MyStruct.h'); coder.cinclude('createStruct.h'); coder.cinclude('useStruct.h'); % initialize variables before use in = coder.opaque('MyStruct'); out = 0; % call C functions in = coder.ceval('createStruct',a,b); out = coder.ceval('useStruct',in); end
createStruct функция выводит тип структуры C:
#include <stdio.h>
#include <stdlib.h>
#include "MyStruct.h"
#include "createStruct.h"
struct MyStruct createStruct(double a, double b) {
struct MyStruct out;
out.p1 = a;
out.p2 = b;
return out;
}
useStruct выполняет операцию над типом C:
#include "MyStruct.h"
#include "useStruct.h"
double useStruct(struct MyStruct in) {
return in.p1 + in.p2;
}
Чтобы создать код, укажите исходные файлы (.c) в качестве входных данных:
codegen addCTypes -args {1,2} -report createStruct.c useStruct.c
Code generation successful: To view the report, open('codegen/mex/addCTypes/html/report.mldatx').
В этом примере показано, как интегрировать внешний код, который работает с массивом стиля C с кодом MATLAB ®. Внешний код вычисляет суммирование по данным массива. Можно настроить код для изменения входных данных или вычислений.
В этом примере показано, как объединить несколько различных элементов функций интеграции внешнего кода. Например, вы:
Интерфейс с внешним типом структуры с помощью coder.cstructname
Интерфейс с внешним типом указателя с помощью coder.opaque
Выполнение внешнего кода с помощью coder.ceval
Передача данных по ссылке на внешний код с помощью coder.ref
Изучите интегрированный код
Функция extSum использует внешний код C для вычисления операции суммирования для массива 32-разрядных целых чисел. Размер массива определяется пользовательским вводом.
function x = extSum(u) %#codegen % set bounds on input type to use static memory allocation u = int32(u); assert(0 < u && u < 101); % initialize an array temparray = int32(1):u; % declare an external structure and use it s = makeStruct(u); x = callExtCode(s, temparray);
Чтобы упростить создаваемый код, необходимо задать границы размера массива. Ограничения предотвращают использование динамического выделения памяти в сгенерированном коде.
Функция makeStruct объявляет тип структуры MATLAB и инициализирует одно из полей для типа указателя с помощью coder.opaque. Структура C, соответствующая этому определению, содержится в файле заголовка, который предоставляется с помощью HeaderFile в параметре coder.cstructname функция. Тип структуры C обеспечивает простое представление для массива целых чисел.
function s = makeStruct(u) % create structure type based on external header definition s.numel = u; s.vals = coder.opaque('int32_T *','NULL'); coder.cstructname(s,'myArrayType','extern','HeaderFile','arrayCode.h');
Если тип внешней структуры полностью инициализирован, он передается как ввод во внешний код в callExtCode функция. Эта функция инициализирует массив, вызывает операцию над массивом, чтобы вернуть один выход, а затем освобождает инициализированную память.
function x = callExtCode(s, temparray) % declare output type x = int32(0); % declare external source file coder.updateBuildInfo('addSourceFiles','arrayCode.c'); % call c code coder.ceval('arrayInit',coder.ref(s),coder.ref(temparray)); x = coder.ceval('arraySum',coder.ref(s)); coder.ceval('arrayDest',coder.ref(s));
Функция использует coder.updateBuildInfo для предоставления файла .c генератору кода.
Создание функции MEX
Для создания функции MEX, которую можно запустить и протестировать в MATLAB, введите:
codegen extSum -args {10}
Code generation successful.
Протестируйте функцию MEX. Введите:
extSum_mex(10)
ans = int32 55
Внешний код C, содержащийся в файлах arrayCode.c и arrayCode.h, использует пользовательское определение типа int32_T. Созданный код MEX создает и использует это пользовательское определение типа. Если требуется создать автономный (lib, dll или exe) код, использующий этот пользовательский тип данных, можно изменить DataTypeReplacement свойства объекта конфигурации. См. раздел Сопоставление типов MATLAB типам в сгенерированном коде.
codegen | coder.ceval | coder.cinclude | coder.cstructname | coder.opaque | coder.ref | coder.reservedName | coder.rref | coder.wref