Из вашего кода MATLAB® можно непосредственно вызвать внешний код C/C++, также названный пользовательским кодом или унаследованным кодом. Генератор кода интегрирует ваш код C/C++ в код C/C++, сгенерированный от MATLAB. Интегрируйте код, когда у вас будут внешние библиотеки, оптимизированный код или объектные файлы, разработанные на C/C++. Следующее является некоторыми первичными рабочими процессами для внешней интеграции кода. Для большего количества примеров смотрите страницу с описанием 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
c:
#include <stdio.h> #include <stdlib.h> #include "adder.h" double adder(double in1, double in2) { return in1 + in2; }
Чтобы интегрировать adder
с вашим кодом MATLAB, вам нужен заголовочный файл, который содержит прототипа функции. Смотрите файл adder.h
h:
double adder(double in1, double in2);
Используйте команду coder.ceval
, чтобы вызвать функцию C в mathOpsIntegrated.m
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)
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++. Когда вы передаете данные ссылкой, программа не должна копировать данные от одной функции до другого. С передачей значением код С может возвратить только единственную скалярную переменную. С передачей ссылкой код С может возвратить несколько переменных, включая массивы.
Считайте функцию MATLAB adderRef
. Эта функция использует внешний код С, чтобы добавить два массива. 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
Код С, 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 'ФАЙЛ *' тип, в MATLAB нет никакого соответствующего типа. Чтобы взаимодействовать с этим типом данных в вашем коде MATLAB, необходимо инициализировать его при помощи функционального coder.opaque
. В случае типов структуры можно использовать coder.cstructname
.
Например, считайте функцию MATLAB addCTypes.m
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 использует внешний код С, чтобы вычислить операцию суммирования на массиве 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}
Протестируйте 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.rref
| coder.wref