exponenta event banner

Код C/C + + вызова из кода MATLAB

Из кода 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

В этом примере показано, как интегрировать простую функцию 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

Язык 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 типам в сгенерированном коде.

См. также

| | | | | | | |

Связанные темы