-
void
FEC_Initialize
()¶ CAPIインタフェースを初期化. この関数は他のCAPI関数よりも先に、かなあらず呼び出さなければならない. アプリケーションスタート時に即呼びだすとよい.
-
void
FEC_Finalize
()¶ CAPIインタフェースをシャットダウン. この関数は CAPIの全ての使用を終えた後に一度呼ぶ. アプリケーション終了時に呼ぶと良い.
-
void
FEC_EnableDebug
(int runServer)¶ Core デバッガを有効化. 有効にした場合コード最適化をオフにし、Dwarfデバッグインフォをコンパイルコードへ埋め込む. 実行サーバ(runServer)が非ゼロの場合、デバッグサーバプロセスもともに起動し、Core プロセスの制御を担う. gdbなどの外部デバッガを使用する場合、実行サーバをゼロに設定.
C言語インタフェース¶
この節では、C言語インタフェースを通じてCAPIを利用するアプリケーションから必要になる一般的なプラクティスについて深く掘り下げます。C言語インタフェースの利用予定がないのであればこの節を読む必要はありません。
名前空間¶
C言語インタフェースの全ての型と関数呼び出しは、 FEC_...
; として始まります。例えば FEC_ClientCreate()
。これには、CAPI関連のコードの特定と、名前空間の衝突を最小化という2つの目的をより簡単に叶えるためです。
オブジェクト生存サイクル¶
C言語では、オブジェクトが自動でスコープ外となる機構をそなえないため、Cのインタフェースを用いる CAPI プログラマーには、Cインタフェースから返すオブジェクトのライフサイクルを、手動で管理する責務があります。
参照カウントされるオブジェクト¶
Cインタフェースにある「高レベルオブジェクト」は全て参照カウントされます。以下を含みます:
- Clients (
FEC_ClientRef
; クライアントとアプリケーションの生存サイクル 参照) - Nodes, Operators, Bindings, Events, EventHandlers (
FEC_NodeRef
,FEC_BindingRef
, etc.; dg-objects 参照)
参照カウントされるオブジェクトは全て、型 FEC_Ref
の基本オブジェクトの 『インスタンス』です。さらに名前末尾に Ref
と付与されています。参照カウントされるオブジェクトは常に、 Create あるいは CreateWith... (例 FEC_ClientCreate()
) とつけ作成します。不要になったのであればそのオブジェクトの FEC_RefRelease()
関数をプログラマの責務として呼びだします。実行時の FEC_RefRelease()
呼び出し失敗は、全参照カウントオブジェクトはメモリ、リソースリークを引き起こします。
APIレファレンス¶
-
FEC_Ref
¶ CAPIにおける一般的な参照型. 多くのCAPI関数でこの型を『継承』した参照を返す. (例参照
FEC_ClientRef
andFEC_DGNodeRef
). Cインタフェースを使用する際, 参照はプログラマが管理の責務を負う. 不要になったのであれば参照を開放すること. さもないとメモリ、リソースのリークを起こし最悪終了時ハングする.
-
void
FEC_RefRetain
(FEC_Ref ref)¶ 参照を保持する; ある参照の参照カウントを一つ加算, 開放のためには
FEC_RefRelease()
をさらに一回追加で呼び出す. FEC_NULL_REF 参照に対しこの関数を呼び出しても何もなさない.この関数は通常必要となることはない.
Variants¶
参照カウントオブジェクトにはさらに、区別されたオブジェクトのクラス ―Cインタフェースで使用する際手動でライフサイクル管理を必要とする― がある。 variant がヘテロジニアス ―異種起源なデータの一般的なコンテナである。Fabric Core 内外でのデータの受け渡しのための大部分の呼び出しにVariant(s) を使用しています。 variants で詳述します。
Variants は常に FEC_VariantInit...
ではじまる呼び出しを使用し作成します。同様 FEC_VariantDispose()
ではじまる呼び出しにより(必要なくなったら)破棄します。参照カウントオブジェクトと同じように不要となったら必ず FEC_VariantDispose
を呼びます。さもないとメモリ、リソースリークをひきおこします。
注釈
このルールに特記すべき例外はありません: variant が nullである場合(つまりFEC_VariantIsNull()
が true を返す)のであれば、FEC_VariantDispose
を呼ぶ必要はありません。(まだ安全ではあります)エラーハンドリングのコードを単純化できます。エラーハンドリング¶
C言語には(良い)一般的な例外機構が存在しないので、CAPI のCインタフェースでは例外機構の提供が限定されたものとなっています。つまり、プログラマが失敗する可能性のある CAPIの呼び出し部分全ての箇所に例外をクエリする必要があります。CAPIでの『例外』とは例外を記述した単純なCの文字列です。例外を最後に捕捉することになるエントリ関数は、 FEC_GetLastExceptionCString()
; です。最終例外が存在しないのであれば NULL を返します。
APIレファレンス¶
-
char const *
FEC_GetLastExceptionCString
()¶ 最終例外を C文字列として戻す, 例外が存在しないのであれば NULL を返す.
警告
この関数が返す値は, コール後大半の CAPI関数 ―FEC_ClearLastException()
を含むで非値(つまりなくなる)となる.
-
uint32_t
FEC_GetLastExceptionLength
()¶ 最終例外の文字列の長さを戻す. 例外が無いのであれば, 0 を戻す.
-
void
FEC_ClearLastException
(void)¶ 最終例外をクリアする.
FEC_GetLastExceptionCString()
は NULL を返す. 最終例外がないのであれば何もなさない.注釈
この関数の呼び出し後はFEC_GetLastExceptionCString()
の返す値は無効(invalid)なものとなる.
Cインタフェースの例¶
以下のサンプルコードで CAPIへの C言語インタフェースの用例を示す.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | #include <FabricCore.h>
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char **argv )
{
char const *exceptionCString;
FEC_ClientCreateOptions createOptions;
FEC_ClientRef client;
FEC_KLSourceFile sourceFiles[1] = {
"vec3.kl",
"\
struct Vec3 {\n\
Float32 x, y, z;\n\
};\n\
function Float32 Vec3.normSq() {\n\
return this.x*this.x + this.y*this.y + this.z*this.z;\n\
}\n\
function Float32 Vec3.norm() {\n\
return sqrt(this.normSq());\n\
}\n\
"
};
FEC_DGOperatorRef dgOperator;
char const *parameterLayout[2] = { "self.vec3", "self.norm" };
FEC_DGBindingRef dgBinding;
FEC_DGNodeRef dgNode;
float vec3Data[1024*3];
float normData[1024];
uint32_t i;
FEC_Initialize();
memset( &createOptions, 0, sizeof(createOptions) );
createOptions.guarded = 1;
client = FEC_ClientCreate( NULL, NULL, &createOptions );
exceptionCString = FEC_GetLastExceptionCString();
if ( exceptionCString )
{
printf( "Caught exception: %s\n", exceptionCString );
exit( 1 );
}
FEC_RegisterKLExtension(
client,
"Vec3",
"1.0.0",
"",
1,
sourceFiles,
true,
false
);
exceptionCString = FEC_GetLastExceptionCString();
if ( exceptionCString )
{
printf( "Caught exception: %s\n", exceptionCString );
exit( 1 );
}
dgOperator = FEC_DGOperatorCreate(
client,
"testOperator1",
"test.kl",
"\
require Vec3;\n\
\n\
operator testOp(Vec3 vec3, io Float32 norm) {\n\
norm = vec3.norm();\n\
}\n\
",
"testOp"
);
dgBinding = FEC_DGBindingCreate(
dgOperator,
2,
parameterLayout
);
exceptionCString = FEC_GetLastExceptionCString();
if ( exceptionCString )
{
printf( "Caught exception: %s\n", exceptionCString );
exit( 1 );
}
dgNode = FEC_DGNodeCreate( client, "testNode1" );
FEC_DGContainerAddMember_Variant( dgNode, "vec3", "Vec3", NULL );
FEC_DGContainerAddMember_Variant( dgNode, "norm", "Float32", NULL );
FEC_DGContainerSetSize( dgNode, 1024 );
for ( i=0; i<1024; ++i )
{
vec3Data[3*i+0] = (float)(i+0);
vec3Data[3*i+1] = (float)(2*i+1);
vec3Data[3*i+2] = (float)(i+2);
}
FEC_DGContainerSetMemberAllSlicesData( dgNode, "vec3", sizeof(vec3Data), vec3Data );
FEC_DGNodeAppendBinding( dgNode, dgBinding );
exceptionCString = FEC_GetLastExceptionCString();
if ( exceptionCString )
{
printf( "Caught exception: %s\n", exceptionCString );
exit( 1 );
}
FEC_DGNodeEvaluate( dgNode );
FEC_DGContainerGetMemberAllSlicesData( dgNode, "norm", sizeof(normData), normData );
for ( i=0; i<8; ++i )
printf( "norm[%u] = %g\n", (unsigned)i, normData[i] );
printf( "...\n" );
for ( i=1016; i<1024; ++i )
printf( "norm[%u] = %g\n", (unsigned)i, normData[i] );
FEC_RefRelease( dgNode );
FEC_RefRelease( dgBinding );
FEC_RefRelease( dgOperator );
FEC_RefRelease( client );
FEC_Finalize();
return 0;
}
|