Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (日本語) » SQL Anywhere サーバ - プログラミング » SQL Anywhere データ・アクセス API » SQL Anywhere 外部関数 API

 

外部関数呼び出し API メソッドの使用

get_value コールバック
short (SQL_CALLBACK *get_value)
(
    void *         arg_handle,
    a_sql_uint32   arg_num,
    an_extfn_value *value
);

get_value コールバック関数は、外部関数とのインタフェースとして動作するストアド・プロシージャまたは関数に渡されたパラメータの値を取得するために使用します。失敗した場合は 0 を返し、それ以外の場合は 0 以外の結果を返します。get_value を呼び出した後、an_extfn_value 構造体の total_len フィールドには値全体の長さが入ります。piece_len フィールドには、get_value を呼び出して取得された部分の長さが入ります。piece_len は必ず total_len 以下の値になります。piece_len が total_len よりも小さい場合は、2 番目の関数 get_piece を呼び出して残りの部分を取得できます。total_len フィールドが有効になるのは、最初の get_value が呼び出された後です。このフィールドは、get_piece の呼び出しによって変更される remain_len フィールドでオーバーレイされます。したがって、total_len フィールドの値を後で使用する場合は、get_value を呼び出した直後にこのフィールドの値を保存しておく必要があります。

get_piece コールバック
short (SQL_CALLBACK *get_piece)
(
    void *         arg_handle,
    a_sql_uint32   arg_num,
    an_extfn_value *value,
    a_sql_uint32   offset
);

パラメータ全体の値を一度に返せない場合は、get_piece 関数を繰り返し呼び出して、パラメータ値の残りの部分を取得できます。

get_value と get_piece の両方を呼び出して返されたすべての piece_len 値の合計が、get_value を呼び出した後で total_len フィールドに返された初期値に加算されます。get_piece の呼び出し後、total_len をオーバーレイする remain_len フィールドには未取得分の長さ (値) が示されます。

get_value コールバックおよび get_piece コールバックの使用

次に示すのは、get_value と get_piece を使用して、LONG VARCHAR パラメータなどの文字列パラメータの値を取得する例です。

外部関数のラッパは次のように宣言されているとします。

CREATE PROCEDURE mystring( IN instr LONG VARCHAR )
  EXTERNAL NAME 'mystring@mystring.dll';

外部関数を SQL から呼び出すには、次のような文を使用します。

call mystring('Hello world!');

C で記述された mystring 関数を Windows オペレーティング・システムに実装する例を次に示します。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include "extfnapi.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
      )
{
    return TRUE;
}

extern "C" __declspec( dllexport )
a_sql_uint32 extfn_use_new_api( void )
{
    return( EXTFN_API_VERSION );
}

extern "C" __declspec( dllexport ) 
void mystring( an_extfn_api *extapi, void *arg_handle )
{
    short               result;
    an_extfn_value      arg;
    unsigned            offset;
    char                *string;

    result = extapi->get_value( arg_handle, 1, &arg );
    if( result == 0 || arg.data == NULL )
    {
        return; // no parameter or parameter is NULL
    }
    string = (char *)malloc( arg.len.total_len + 1 );
    offset = 0;
    for( ; result != 0; ) {
         if( arg.data == NULL ) break;
         memcpy( &string[offset], arg.data, arg.piece_len );
         offset += arg.piece_len;
         string[offset] = '\0';
         if( arg.piece_len == 0 ) break;
         result = extapi->get_piece( arg_handle, 1, &arg, offset );
    }
    MessageBoxA( NULL, string,
          "SQL Anywhere",
          MB_OK | MB_TASKMODAL );
    free( string );
    return;
}
set_value コールバック
short (SQL_CALLBACK *set_value)
(
    void *         arg_handle,
    a_sql_uint32   arg_num,
    an_extfn_value *value
    short          append
);

set_value コールバック関数は、OUT パラメータおよびストアド関数の RETURNS 結果の値を設定するために使用します。RETURNS 値を設定するには、arg_num 値を 0 にします。次はその例です。

an_extfn_value      retval;

retval.type = DT_LONGVARCHAR;
retval.data = result;
retval.piece_len = retval.len.total_len = (a_sql_uint32) strlen( result );
extapi->set_value( arg_handle, 0, &retval, 0 );

set_value の append 引数は、指定されたデータを既存のデータと置き換えるか (false)、または既存のデータに追加するか (true) を指定します。append=FALSE を指定して set_value を呼び出してから、同じ引数に対して append=TRUE を指定して呼び出してください。固定長データ型の場合、append 引数は無視されます。

NULL を返すには、an_extfn_value 構造体の data フィールドを NULL に設定します。

set_cancel コールバック
void (SQL_CALLBACK *set_cancel)
(
    void *arg_handle,
    void *cancel_handle
);

外部関数では、IN または INOUT パラメータの値を取得し、OUT パラメータおよびストアド・関数の RETURNS 結果の値を設定することができます。ただし、取得したパラメータ値が無効になっていたり、値を設定する必要がなくなっている場合があります。これは、SQL 文の実行が取り消された場合に発生します。また、アプリケーションがデータベース・サーバから不意に切断された場合に発生することもあります。この問題を処理するには、extfn_cancel という特別なエントリ・ポイントをライブラリに定義します。この関数が定義されていると、サーバは実行中の SQL 文が取り消される場合に必ずこの関数を呼び出します。

extfn_cancel 関数は、適切と思われるさまざまな方法で使用できるハンドルを指定して呼び出されます。一般的にこのハンドルは、SQL 文の呼び出しが取り消されたことを示すフラグを間接的に設定する場合に使用します。

渡されるハンドルの値は、set_cancel コールバック関数を使用して、外部ライブラリの関数で設定することができます。次のコード・フラグメントがその例です。

extern "C" __declspec( dllexport )
void extfn_cancel( void *cancel_handle )
{
    *(short *)cancel_handle = 1;
}

extern "C" __declspec( dllexport ) 
void mystring( an_extfn_api *api, void *arg_handle )
{
.
.
.
    short  canceled = 0;

    extapi->set_cancel( arg_handle, &canceled );
.
.
.
    if( canceled )

静的なグローバル "canceled" 変数を設定することは不適切です。これは、通常はありえない、すべての接続のすべての SQL 文が取り消されると誤って解釈されることがあるためです。そのために、set_cancel コールバック関数が提供されています。set_cancel を呼び出す前に、"canceled" 変数を必ず初期化してください。

外部関数の重要ポイントにある "canceled" 変数の設定を確認しておく必要があります。たとえば、get_value や set_value などの外部ライブラリ呼び出し API 関数の呼び出し前や後などが重要ポイントです。extfn_cancel が呼び出された結果、変数が設定されると、外部関数は適切な終了アクションを実行することができます。前述の例に基づいたコード・フラグメントを次に示します。

if( canceled )
{
    free( string );
    return;
}
注意

任意の引数の get_piece 関数は、同じ引数の get_value 関数の直後にのみ呼び出すことができます。

OUT パラメータで get_value を呼び出すと、an_extfn_value 構造体の type フィールドに引数のデータ型が設定されて返され、an_extfn_value 構造体の data フィールドに NULL が設定されて返されます。

SQL Anywhere インストール・ディレクトリの SDK\Include フォルダのヘッダ・ファイル extfnapi.h に、詳細な注意事項が記載されています。

次の表に、an_extfn_api に定義されている関数が false を返す条件を示します。

関数 true の場合は 0 を返し、それ以外の場合は 1 を返す条件
get_value()
  • arg_num が無効な場合。たとえば、arg_num が外部関数の引数の数より大きい場合。

get_piece()
  • arg_num が無効な場合。たとえば、arg_num が前に呼び出された get_value で使用した引数番号に対応していない場合。

  • オフセットが arg_num 引数の値の合計長より大きい場合。

  • get_value が呼び出される前に呼び出された場合。

set_value()
  • arg_num が無効な場合。たとえば、arg_num が外部関数の引数の数より大きい場合。

  • 引数 arg_num が入力専用の場合。

  • 指定された値の型が引数 arg_num の型と一致しない場合。