C++言語インタフェース

この節では、C++言語インタフェースを通じてCAPIを利用するアプリケーションから必要になる一般的なプラクティスについて深く掘り下げます。C++言語インタフェースの利用予定がないのであればこの節を読む必要はありません。

C++ にはライフサイクル管理、例外機能両方あるので、CAPIのC++インタフェースを使用する際、プログラマの責務を軽減します。

名前空間

全ての C++ インタフェースのオブジェクト(クラス),関数は、C++名前空間 FabricCore の中にあります。プログラマは、明示的な名前空間の使用か暗黙の使用どちらか選択できます。明示的な使用であれば、CAPI オブジェクト(関数)を FabricCore::... プリフィクスを付け使用します。例: FabricCore::DGNode 暗黙の名前空間の使用であれば、プリフィクスを省略できます(ただし、コンパイル時、プログラム中、他のシンボルとの名前の衝突を起きさないようにしましょう)

using namespace FabricCore;

CAPI C++ インタフェースを使用するソースファイルの最初に記述します。

オブジェクト生存サイクル

CAPI C++インタフェース使用の際は、参照カウントオブジェクト,variant双方、スコープ外へといった時点で自動で開放されます。CAPI C++オブジェクトのスコープについての規則は、他のC++オブジェクトにならいます。

エラーハンドリング

C++ インタフェースではエラーハンドリングに C++ 標準の例外ハンドリングを使用しています。CAPI C++インタフェースを使用する際、発生するエラーは FabricCore::Exception 型の C++例外として送信します。これを通常の catch ( FabricCore::Exception e ) { ... } ステートメントで補足することができます。より詳しくは exceptions を参照してください。

用例

以下のサンプルコードで 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
#include <FabricCore.h>

#include <stdio.h>

int main( int argc, char **argv )
{
  FabricCore::Initialize();

  FabricCore::Client::CreateOptions createOptions;
  memset( &createOptions, 0, sizeof(createOptions) );
  createOptions.guarded = true;

  FabricCore::Client client( NULL, NULL, &createOptions );

  FabricCore::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\
"
    }
  };
  FabricCore::RegisterKLExtension(
    client,
    "Vec3",
    "1.0.0",
    "", // override
    1,
    sourceFiles,
    true, // load
    false // reload
    );

  FabricCore::DGOperator dgOperator(
    client,
    "testOperator1",
    "test.kl",
    "\
require Vec3;\n\
\n\
operator testOp(Vec3 vec3, io Float32 norm) {\n\
  norm = vec3.norm();\n\
}\n\
",
    "testOp"
    );

  char const *parameterLayout[2] = { "self.vec3", "self.norm" };
  FabricCore::DGBinding dgBinding(
    dgOperator,
    2,
    parameterLayout
    );

  FabricCore::DGNode dgNode( client, "testNode1" );
  dgNode.addMember( "vec3", "Vec3" );
  dgNode.addMember( "norm", "Float32" );
  dgNode.setSize( 1024 );
  float vec3Data[1024*3];
  for ( uint32_t 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);
  }
  dgNode.setMemberAllSlicesData( "vec3", sizeof(vec3Data), vec3Data );
  dgNode.appendBinding( dgBinding );
  dgNode.evaluate();
  float normData[1024];
  dgNode.getMemberAllSlicesData( "norm", sizeof(normData), normData );
  for ( uint32_t i=0; i<8; ++i )
    printf( "norm[%u] = %g\n", unsigned(i), normData[i] );
  printf( "...\n" );
  for ( uint32_t i=1016; i<1024; ++i )
    printf( "norm[%u] = %g\n", unsigned(i), normData[i] );

  FabricCore::Finalize();

  return 0;
}