Из вашего 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 и заставить его перестать работать. Чтобы отлажить код и проанализировать сообщения об ошибке из компиляции, смотрите вкладку Build Logs в отчете о генерации кода.
В этом примере показано, как интегрировать простую функцию C с кодом MATLAB ® с помощью coder.ceval
. Рассмотрим функцию MATLAB, mathOps
:
function [added, multed] = mathOps(in1, in2) added = in1+in2; multed = in1*in2; end
В данном примере предположим, что вы хотите реализовать операцию сложения с использованием внешнего кода С Рассмотрим функцию 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
как вход. Для тестирования Кода С выполните 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 и из нее.
Pass by reference является важным методом для интегрирования кода C/C + +. Когда вы передаете данные по ссылке, программе не нужно копировать данные из одной функции в другую. С передачей по значению код С может вернуть только одну скалярную переменную. С помощью ссылки pass by, код С может вернуть несколько переменных, включая массивы.
Рассмотрим функцию MATLAB adderRef
. Эта функция использует внешний код С, чтобы добавить два массива. The 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
The Кода С, 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]; } }
Чтобы создать код С, вы должны предоставить заголовочный файл, cAdd.h
, с подписью функции:
void cAdd(const double* in1, const double* in2, double* out, int numel);
Протестируйте Код С, сгенерировав 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 '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
The 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; }
The 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 использует внешние Коды С для вычисления операции суммирования массива из 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
Внешний код С, содержащийся в файлах 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