Вызов кода 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 и заставить его перестать работать. Чтобы отлажить код и проанализировать сообщения об ошибке из компиляции, смотрите вкладку 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

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

См. также

| | | | | | | |

Похожие темы