Из вашего кода MATLAB® можно непосредственно вызвать внешний код C/C++, также названный пользовательским кодом или унаследованным кодом. Чтобы вызвать функции C/C++, используйте coder.ceval
. Генератор кода интегрирует ваш код C/C++ в код C/C++, сгенерированный из MATLAB. Интегрируйте код, когда существуют внешние библиотеки, оптимизированный код или объектные файлы, разработанные на C/C++, который вы хотите использовать со своим сгенерированным кодом. Когда внешний код использует типы переменных, которые не заданы или распознаны MATLAB, используют функцию coder.opaque
в сочетании с coder.ceval
.
Следующее является некоторыми первичными рабочими процессами для внешней интеграции кода. Для большего количества примеров смотрите страницу с описанием 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)
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
. Эта функция использует 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