Main Content

coder.ceval

外部 C/C++ 関数の呼び出し

説明

coder.ceval(cfun_name) は、cfun_name で指定された外部 C/C++ 関数を実行します。外部 C/C++ ソース ファイルまたはライブラリ内で cfun_name を定義します。外部ソース、ライブラリおよびヘッダー ファイルをコード ジェネレーターに提供します。

coder.ceval(cfun_name,cfun_arguments) は、引数 cfun_arguments を使用して cfun_name を実行します。cfun_arguments は、cfun_name が要求する順序による入力引数のコンマ区切りリストです。

既定の設定では、C/C++ が引数の値渡しをサポートするときはいつでも、coder.ceval は C/C++ 関数に引数を値渡しします。coder.ceval が引数を参照渡しするには、coder.refcoder.rrefcoder.wref 構成を使用します。たとえば、引数が配列のときなど、C/C++ が引数の値渡しをサポートしない場合、coder.ceval は引数を参照渡しします。coder.refcoder.rref、または coder.wref を使用しないと、引数のコピーが生成コードに現れ、配列に対して MATLAB® セマンティクスを強制する可能性があります。

coder.ceval('-global',cfun_name)cfun_name を実行し、cfun_name が 1 つ以上の MATLAB グローバル変数を使用することを示します。その後、コード ジェネレーターは、このグローバル変数の使用と一致するコードを生成できます。

メモ

-global フラグは、コード生成でのみサポートされます。MATLAB 関数ブロックで coder.ceval の呼び出し中にこのフラグを含めることはできません。

coder.ceval('-global',cfun_name,cfun_arguments) は引数 cfun_arguments を使用して cfun_name を実行し、cfun_name が 1 つ以上の MATLAB グローバル変数を使用することを示します。

coder.ceval('-gpudevicefcn',devicefun_name,devicefun_arguments) により、CUDA® の GPU 関数 __device__ をカーネル内から呼び出すことができます。'-gpudevicefcn'coder.ceval に対して、ターゲット関数が GPU デバイス上であることを示します。devicefun_name は関数 __device__ の名前であり、devicefun_argumentsdevicefun_name が求める順番の入力引数のコンマ区切りのリストです。このオプションには GPU Coder™ 製品が必要です。

coder.ceval('-layout:rowMajor',cfun_name,cfun_arguments) は、引数 cfun_arguments を使用して cfun_name を実行し、行優先のレイアウトで保存されたデータを渡します。列優先のレイアウトを使用する関数から呼び出されると、コード ジェネレーターは入力を行優先のレイアウトに変換し、出力を列優先のレイアウトに変換します。構文を短くするには、coder.ceval('-row',...) を使用します。

coder.ceval('-layout:columnMajor',cfun_name,cfun_arguments) は、引数 cfun_arguments を使用して cfun_name を実行し、列優先のレイアウトで保存されたデータを渡します。行優先のレイアウトを使用する関数から呼び出されると、コード ジェネレーターは入力を列優先のレイアウトに変換し、出力を行優先のレイアウトに変換します。構文を短くするには、coder.ceval('-col',...) を使用します。

coder.ceval('-layout:any',cfun_name,cfun_arguments) は、引数 cfun_arguments を使用して cfun_name を実行し、配列のレイアウトが一致しない場合でも、現在の配列レイアウトを使用してデータを渡します。コード ジェネレーターは入力データまたは出力データの配列レイアウトを変換しません。

cfun_return = coder.ceval(___)cfun_name を実行し、C/C++ 関数が return ステートメントで返す値に対応する 1 つのスカラー値 cfun_return を返します。C/C++ との一貫性をもたせるため、coder.ceval はスカラー値のみを返すことができます。配列を返すことはできません。このオプションは、前述の構文のすべての入力引数の組み合わせで使用できます。

すべて折りたたむ

C コードの生成元の MATLAB 関数から、C 関数 foo(u) を呼び出します。

関数 foo の C ヘッダー ファイル foo.h を作成します。この関数は、double 型の入力パラメーターを 2 つ受け入れ、double 型の値を返します。

double foo(double in1, double in2);

C 関数 foo.c を作成します。

#include <stdio.h>
#include <stdlib.h>
#include "foo.h"

double foo(double in1, double in2)
{
  return in1 + in2;
}

coder.ceval を使用して foo を呼び出す関数 callfoo を記述します。関数でコード ジェネレーターにソース ファイルとヘッダー ファイルを提供します。

function y = callfoo  %#codegen
y = 0.0;
if coder.target('MATLAB')
    % Executing in MATLAB, call MATLAB equivalent of
    % C function foo
    y = 10 + 20;
else
    % Executing in generated code, call C function foo
    coder.updateBuildInfo('addSourceFiles','foo.c');
    coder.cinclude('foo.h');
    y = coder.ceval('foo', 10, 20);
end
end

関数 callfoo の C ライブラリ コードを生成します。関数 codegen によって C コードが \codegen\lib\callfoo サブフォルダー内に生成されます。

codegen -config:lib callfoo -report

MATLAB コードから C ライブラリ関数を呼び出します。

MATLAB 関数 myabsval を記述します。

function y = myabsval(u)   
%#codegen
y = abs(u);

入力パラメーターのサイズ、型および実数/複素数を指定するために、-args オプションを使用して myabsval の C スタティック ライブラリを生成します。

codegen -config:lib myabsval -args {0.0}
関数 codegen はライブラリ ファイル myabsval.lib およびヘッダー ファイル myabsval.h をフォルダー \codegen\lib\myabsval 内に作成します (ライブラリ ファイルの拡張子はプラットフォームによって異なります)。関数 myabsval_initialize と 関数 myabsval_terminate を同じフォルダー内に生成します。

coder.ceval を使用して生成された C ライブラリ関数を呼び出す MATLAB 関数を記述します。

function y = callmyabsval(y)  
%#codegen
% Check the target. Do not use coder.ceval if callmyabsval is
% executing in MATLAB
if coder.target('MATLAB')
  % Executing in MATLAB, call function myabsval
  y = myabsval(y);
else
  % add the required include statements to generated function code
  coder.updateBuildInfo('addIncludePaths','$(START_DIR)\codegen\lib\myabsval');
  coder.cinclude('myabsval_initialize.h');
  coder.cinclude('myabsval.h');
  coder.cinclude('myabsval_terminate.h');

  % Executing in the generated code. 
  % Call the initialize function before calling the 
  % C function for the first time
  coder.ceval('myabsval_initialize');

  % Call the generated C library function myabsval
  y = coder.ceval('myabsval',y);
  
  % Call the terminate function after
  % calling the C function for the last time
  coder.ceval('myabsval_terminate');
end

MEX 関数 callmyabsval_mex を生成します。コマンド ラインで、生成されたライブラリ ファイルを指定します。

codegen -config:mex callmyabsval codegen\lib\myabsval\myabsval.lib -args {-2.75}

コマンド ラインでライブラリを指定する代わりに、coder.updateBuildInfo を使用して関数内でライブラリを指定できます。このオプションを使用してビルドを事前設定します。次の行を else ブロックに追加します。

coder.updateBuildInfo('addLinkObjects','myabsval.lib','$(START_DIR)\codegen\lib\myabsval',100,true,true);

メモ

START_DIR マクロは MATLAB Coder™ を使用したコードの生成に対してのみサポートされています。

ライブラリ関数 myabsval を呼び出す MEX 関数 callmyabsval_mex を実行します。

callmyabsval_mex(-2.75)
ans =

    2.7500

MATLAB 関数 callmyabsval を呼び出します。

callmyabsval(-2.75)
ans =

    2.7500
関数 callmyabsval は、MATLAB およびコード生成での実行について目的の動作を示します。

グローバル変数を変更する C 関数を呼び出すときは '-global' フラグを使用します。

C 関数 addGlobal を呼び出す MATLAB 関数 useGlobal を記述します。'-global' フラグを使用して、C 関数でグローバル変数を使用することをコード ジェネレーターに示します。

function y = useGlobal()
global g;
t = g;
% compare execution with/without '-global' flag
coder.ceval('-global','addGlobal'); 
y = t;
end

関数 addGlobal 用の C ヘッダー ファイル addGlobal.h を作成します。

void addGlobal(void);

ファイル addGlobal.c で C 関数 addGlobal を記述します。この関数には、関数 useGlobal のコード生成時にコード ジェネレーターによって作成されるヘッダー ファイル useGlobal_data.h が含まれます。ヘッダー ファイルには g のグローバル変数宣言が含まれます。

#include "addGlobal.h"
#include "useGlobal_data.h"
void addGlobal(void) {
    g++;
}

useGlobal の MEX 関数を生成します。コード ジェネレーターへの入力を定義するには、ワークスペースでグローバル変数を宣言します。

global g;
g = 1;
codegen useGlobal -report addGlobal.h addGlobal.c
y = useGlobal_mex();

'-global' フラグを使用すると、MEX 関数によって y = 1 という結果が生成されます。'-global' フラグは、C 関数によってグローバル変数が変更される可能性があることをコード ジェネレーターに示します。useGlobal の場合、コード ジェネレーターは次のコードを生成します。

real_T useGlobal(const emlrtStack *sp)
{
  real_T y;
  (void)sp;
  y = g;
  addGlobal();
  return y;
}

'-global' フラグを使用しない場合、MEX 関数によって y = 2 が生成されます。C 関数によって g が変更されるということが示されていないため、コード ジェネレーターは yg が同一であると想定します。次の C コードが生成されます。

real_T useGlobal(const emlrtStack *sp)
{
  (void)sp;
  addGlobal();
  return g;
}

行優先のレイアウトを使用するよう設計された C 関数 testRM を使用しているとします。この関数を、配列で動作する MATLAB の関数 bar に統合しようとしています。関数 bar は、coder.columnMajor 命令を使用して、列優先のレイアウトを使用するよう設計されています。

function out = bar(in)
%#codegen
coder.columnMajor;
coder.ceval('-layout:rowMajor','testRM', ...
    coder.rref(in),coder.wref(out));
end

生成されたコードで、コード ジェネレーターは、変数 in に対して列優先のレイアウトから行優先のレイアウトへのレイアウト変換を挿入してから、それを testRM に渡します。出力変数 out に対して、コード ジェネレーターは列優先に戻すレイアウト変換を挿入します。

一般的に、coder.cevallayout オプションを指定しない場合、外部関数の引数に列優先を使用しているとみなされます。

複素数入力を取るカスタム C コードを呼び出す MATLAB 関数があるとします。MATLAB 関数からの複素数入力を C コードにマッピングできるように C コードの入力パラメーターを定義しなければなりません。

生成されたコードでは、複素数は reim の 2 つのフィールドをもつ struct として定義されます。これらのフィールドは、それぞれ複素数の実数部と虚数部です。この struct は、現在のパスの codegen\lib\functionName フォルダーにあるヘッダー ファイル rtwtypes.h で定義されます。struct は次のように定義されます。

typedef struct {
    real32_T re; /*Real Component*/
    real32_T im; /*Imaginary Component*/
} creal_T;

詳細については、生成コードの型への MATLAB 型のマッピングを参照してください。

統合する C コードには rtwtypes.h ヘッダー ファイルを含めなければなりません。C コード例 foo.c を次に示します。

#include "foo.h"
#include<stdio.h>
#include<stdlib.h>
#include "rtwtypes.h"

double foo(creal_T x) {
    double z = 0.0;
    z = x.re*x.re + x.im*x.im;
    return (z);
}

struct の名前は creal_T です。ヘッダー ファイル foo.h も次のように定義しなければなりません。

#include "rtwtypes.h"
double foo(creal_T x);

MATLAB コードは、複素数入力をもつ関数 coder.ceval を使用して foo.c を実行します。

function y = complexCeval  %#codegen
y = 0.0;
coder.updateBuildInfo('addSourceFiles','foo.c');
coder.cinclude('foo.h');
y = coder.ceval('foo', 10+20i);
end
coder.ceval コマンドは複素数入力を取ります。コード ジェネレーターは、複素数を struct creal_T の変数 x とそのフィールド re および im にマッピングします。

次のコマンドを実行して関数 complexCeval のコードを生成します。

codegen -config:lib -report complexCeval

入力引数

すべて折りたたむ

呼び出す外部 C/C++ 関数の名前。

例: coder.ceval('foo')

データ型: char | string

cfun_name が要求する順序による入力引数のコンマ区切りリスト。

例: coder.ceval('foo', 10, 20);

例: coder.ceval('myFunction', coder.ref(x));

データ型: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 | logical | char | struct
複素数のサポート: あり

制限

  • coder.extrinsic を使用して外部関数として宣言した関数では、coder.ceval を使用することはできません。

  • LCC コンパイラはライブラリの作成時にライブラリ関数の名前の前にアンダースコアを追加します。ライブラリのコンパイラが LCC で、コード生成に LCC 以外のコンパイラを使用する場合は、たとえば coder.ceval('_mylibfun') のように、関数名の前にアンダースコアを追加しなければなりません。ライブラリのコンパイラが LCC 以外の場合、そのライブラリの関数を呼び出す MATLAB コードから LCC を使用してコードを生成することはできません。それらのライブラリ関数の名前には、先頭に LCC コンパイラで必要なアンダースコアが付いていません。

  • プロパティに get メソッド、set メソッド、または検証関数がある場合、またはプロパティが特定の属性をもつ System object™ プロパティである場合、そのプロパティを外部関数に参照で渡すことはできません。一部のプロパティでサポートされない参照渡しを参照してください。

  • 可変サイズの行列は、行優先のコード生成ではエントリポイント パラメーターとしてサポートされていません。

ヒント

  • コード生成では、coder.ceval を呼び出す前に、戻り値と出力引数の型、サイズ、実数/複素数のデータ型を指定しなければなりません。

  • ポインター、FILE 型のファイル I/O、C/C++ マクロなど、MATLAB コードに存在しない変数を受け入れる関数や返す関数に coder.ceval を適用するには、関数 coder.opaque を使用します。

  • coder.ceval は、MATLAB でのコード生成のみに使用してください。コンパイルされていない MATLAB コードでは、coder.ceval はエラーを生成します。MATLAB 関数が MATLAB で実行されているかどうかを判断するには、coder.target を使用します。関数が MATLAB で実行されている場合、MATLAB バージョンの C/C++ 関数を呼び出します。

  • coder.ceval を使用して呼び出される外部コードと生成コードは、同じプロセス内で実行され、メモリを共有します。生成コードで使用されるデータ構造体を含むメモリに外部コードが誤って書き込みを行うと、プロセスが予期しない動作をするか、クラッシュする可能性があります。たとえば、外部コードが終点より後の配列にデータを書き込もうとすると、プロセスが予期しない動作をするか、クラッシュする可能性があります。

  • MATLAB は Windows® プラットフォームで UTF-8 をシステム エンコードとして使用します。その結果、生成された MEX 関数内から行われたシステム呼び出しは、UTF-8 で符号化された文字列を受け入れて返します。一方、MATLAB Coder で生成されたコードは、Windows ロケールで指定されたエンコードを使用してテキスト データを符号化します。このため、MATLAB のエントリポイント関数が coder.ceval を使用して異なるシステム エンコードを想定する外部 C/C++ 関数を呼び出すと、生成された MEX 関数から文字化けが発生する可能性があります。これが発生した場合は、外部 C/C++ 関数を更新してこの状況に対処する必要があります。

拡張機能

C/C++ コード生成
MATLAB® Coder™ を使用して C および C++ コードを生成します。

GPU コード生成
GPU Coder™ を使用して NVIDIA® GPU のための CUDA® コードを生成します。

バージョン履歴

R2011a で導入