- Since
-
- See also
-
他Memberから呼び出せる関数の登録、 また他Memberの関数の呼び出しができます。
関数の登録
C++ Client::func からFuncオブジェクトを作り、 Func::set() で関数を登録し、Client::sync()することで送信されます
関数は関数オブジェクト(ラムダ式など)でもokです。 引数、戻り値は整数、実数、bool、文字列型であれば自由に指定できます。
void hoge() {
std::cout << "hello, world!" << std::endl;
}
double fuga(int a, const std::string &b) {
return 3.1415;
}
wcli.func("hoge").set(hoge);
wcli.func("fuga").set(fuga);
wcli.func("hoge").set([](){ });
wcli.func("fuga").set([](int a, const std::string &b){ return 3.1415; });
set() の代わりに代入演算子(Func::operator=)でも同様のことができます
- 2.0 代入演算子はdeprecatedになりました
- 同じ名前のFuncに複数回関数をセットすると上書きされ、後に登録した関数のみが呼び出されます。 ただし引数や戻り値の型などの情報は更新されず、最初の関数のものと同じになります。
- 関数の中で例外をthrowした場合WebCFace側でcatchされ、エラーメッセージが呼び出し元に返ります。
- 2.0 set()で登録した関数はClient::sync()時に同じスレッドで実行されます。 そのため長時間かかる関数を登録するとその間他の処理がブロックされることになります。
- 関数を非同期(別スレッド)で実行したい場合は Func::setAsync() を使用してください。 ver1.11以前ではset()で登録した関数はすべて非同期実行されていたので、こちらが従来のset()と同じ挙動になります。
- ただしその場合排他制御が必要なら登録する関数内で適切に行ってください
wcli.func("hoge").setAsync([](){
std::this_thread::sleep_for(std::chrono::seconds(5));
return "hello";
});
- Warning
- 2.0 set()で登録した関数はClient::sync() の中で呼び出されるため、
- sync() が呼び出される頻度が少ない場合、呼び出されてから実際に関数を実行するまでにラグが生じます。 その場合はsync()を呼び出す頻度を上げるか、loopSync() を使ってください (4-1. Client 参照)
- set()で登録した関数内で他のクライアントの関数をrun()やrunAsync()で呼び出して結果を受け取ろうとするとデッドロックしてしまいます。 (結果を受け取る処理も sync() で行われるため)
wcli.func("hoge").set([&](){
wcli.member("foo").func("piyo").runAsync().waitFinish();
std::async([&]{
wcli.member("foo").func("piyo").waitFinish();
});
});
JavaScript Client.func からFuncオブジェクトを作り、 Func.set() で関数を登録し、Client.sync()することで送信されます
引数、戻り値はnumber, bool, string型であればいくつでも自由に指定できます。
wcli.func("hoge").set(() => {/* ... */});
wcli.func("hoge").set((a: number, b: string) => 3.1415);
- 関数の中で例外をthrowした場合WebCFace側でcatchされ、エラーメッセージが呼び出し元に返ります。
- 同じ名前のFuncに複数回関数をセットすると上書きされ、後に登録した関数のみが呼び出されます。 ただし引数や戻り値の型などの情報は更新されず、最初の関数のものと同じになります。
Python Client.func からFuncオブジェクトを作り、 Func.set() で関数を登録し、Client.sync()することで送信されます
def hoge(a, b):
return 3.1415
wcli.func("hoge").set(hoge)
wcli.func("lambda").set(lambda x: return x + 5)
- 関数の中で例外をraiseした場合WebCFace側でcatchされ、エラーメッセージが呼び出し元に返ります。
- 同じ名前のFuncに複数回関数をセットすると上書きされ、後に登録した関数のみが呼び出されます。 ただし引数や戻り値の型などの情報は更新されず、最初の関数のものと同じになります。
- setを明示的に呼び出す代わりにfuncオブジェクトをデコレータにすると簡単に登録できます。
@wcli.func("hoge")
def hoge(a, b):
return 3.1415
- デコレータとして使用する場合func()の引数に関数名を書くのを省略すると実際の関数の名前が自動で取得され設定されます。
()
は必須です。(@wcli.func
をデコレータとして使わないでください。) @wcli.func()
def hoge(a, b):
return 3.1415
- 2.0 set() で登録した関数はClient.sync()時に同じスレッドで実行されます。 そのため長時間かかる関数を登録するとその間他の処理がブロックされることになります。
- 関数を非同期(別スレッド)で実行したい場合は Func.set_async() を使用してください。 ver1.11以前ではset()で登録した関数はすべて非同期実行されていたので、こちらが従来のset()と同じ挙動になります。
- set_async() で登録した関数は新しいスレッド(threading.Thread)で実行されます。
def hoge(a, b):
time.sleep(5)
wcli.func("hoge").set_async(hoge)
- Warning
- 2.0 set()で登録した関数はClient.sync() の中で呼び出されるため、
- sync() が呼び出される頻度が少ない場合、呼び出されてから実際に関数を実行するまでにラグが生じます。 その場合はsync()を呼び出す頻度を上げるか、sync(timeout) を使ってください (4-1. Client 参照)
- set()で登録した関数内で他のクライアントの関数をrun()やrun_async()で呼び出して結果を受け取ろうとするとデッドロックしてしまいます。 (結果を受け取る処理も sync() で行われるため)
@wcli.func()
def hoge():
wcli.member("foo").func("piyo").run()
def wait_piyo():
wcli.member("foo").func("piyo").run()
threading.Thread(target=wait_piyo)
setした関数にWebCFace側で排他制御をかける機能(〜ver1.11まで)
C++では呼び出された関数は別スレッドで非同期に実行されます。 これをメインスレッドと同期させたい場合は実行条件を設定することができます。
wcli.func("fuga").setRunCondOnSync();
とすると呼び出された関数の実行は wcli.sync() のときに行われます。
struct ScopeGuard {
static std::mutex m;
ScopeGuard() { m.lock(); }
~ScopeGuard() { m.unlock(); }
};
wcli.func("fuga").setRunCondScopeGuard<ScopeGuard>();
とすると任意のScopeGuardクラスを使うことができます (実行前にScopeGuardのコンストラクタ、実行後にデストラクタが呼ばれます)
また、すべての関数にまとめて条件を設定したい場合は、関数の設定前に
wcli.setDefaultRunCondOnSync();
wcli.setDefaultRunCondScopeGuard<ScopeGuard>();
とするとデフォルトの条件を設定できます。
デフォルトを設定した後個別の関数について条件を設定することもできますし、
wcli.func("fuga").setRunCondNone();
で条件を何も課さないようにできます。
CallHandle
引数と戻り値型
C++ 引数型や戻り値型は関数の型から自動で取得されますが、 引数名などの情報や引数に設定する条件などを Func::setArgs() でセットすることができます。 設定可能な情報の一覧は webcface::Arg を参照
関数をsetする前に呼ぶとエラーになります。 また、実際の関数の引数と個数が一致していなければ std::invalid_argument を投げます。
wcli.func("fuga").setArgs({
});
std::optional< ValAdaptor > init() const
デフォルト値を取得する。
Definition func_info.cc:62
const std::vector< ValAdaptor > & option() const
引数の選択肢を取得する。
Definition func_info.cc:85
- JavaScript 引数名、引数や戻り値の型、その他の引数に関する情報をset関数の引数で指定します。 引数のオプションに関しては Arg を参照
wcli.func("hoge").set(
() => { /*...*/ }, // 関数
valType.float_, // 戻り値の型
[ // 引数の情報
{ name: "a", type: valType.int_, init: 100 },
{ name: "b", type: valType.string_, option: ["aaa", "bbb", "ccc"] },
],
);
Python Pythonではset()関数の引数にオプションで args と return_type を渡すことで型やその他の情報を指定できます。 argsの引数に関しては webcface.Arg を参照
引数名については実際の引数名が自動的に取得されます。
from webcface import Arg
def hoge(a, b):
return 3.1415
wcli.func("hoge").set(hoge, return_type=float, args=[
Arg(type=int, init=100),
Arg(type=str, option=["aaa", "bbb", "ccc"]),
])
デコレータで登録する場合はset()の代わりにfunc()の引数に渡してください。
@wcli.func(return_type=float, args=[
Arg(type=int, init=100),
Arg(type=str, option=["aaa", "bbb", "ccc"]),
])
def hoge(a, b):
return 3.1415
引数と戻り値の型アノテーションをすると、型の指定を省略できます。 また、デフォルト引数も指定されていればそれが使われます。
def hoge(a: int = 100, b: str = "aaa") -> float:
return 3.1415
wcli.func("hoge").set(hoge, args=[
Arg(),
Arg(option=["aaa", "bbb", "ccc"]),
])
2.2 実際の関数の引数とargsで指定した個数が一致していなければAssertionErrorになります。
型変換
- 関数登録時に指定した型と呼び出したときに渡した引数の型が違う場合、呼び出された側のライブラリが自動的に変換してから関数に渡します。
- (ver1.5.3〜1.9.0のserverではすべて文字列型に置き換えられてしまうバグあり、ver1.9.1で修正)
- 変換規則は基本的には呼び出された側の言語仕様の標準に従います。
- 文字列→数値は10進数で変換されます。小数点以下の桁数や、指数表記にするかどうかは未規定です
- 数値→文字列も10進数としてパースされます。数値でない文字列が渡された場合の処理は未規定です
- bool→文字列
- C++: 0, 1
- Python:
False, True 3.0 0, 1
- JavaScript: false, true
- 文字列→bool
- C++:
"1"
のみtrue 1.9.1 空文字列でないときtrue
- Python: 空文字列でないときTrue
- JavaScript: 空文字列でないときtrue
- (C++) 引数を webcface::ValAdaptor 型にすると型変換を行わずに値を受け取ることができます。
- (C) set時に指定した引数の型によらず、callHandleからは常にint,double,文字列のいずれでも値を受け取ることができます。
- (JavaScript) set時に引数の型の情報を指定しなかった場合、型変換を行わず送られてきた値をそのまま関数に渡します。
- (Python) 3.0 関数登録時に指定した型が int,float,bool,str のいずれでもないもしくは未指定の場合、 型変換を行わず送られてきた値をそのまま関数に渡します。
関数をWebUIから隠す
(serverが1.10以降の場合)
関数の名前を半角ピリオドから始めると、Entryが他クライアントに送信されなくなり、 他のMemberやWebUIから関数の存在を隠すことができます。 (Valueなど他のデータ型についても同様です。)
なお半角ピリオド2つから始まる名前はwebcface内部の処理で利用する場合があるので使用しないでください。
以前のバージョンでは名前に関係なく関数を非表示にするオプションがありましたが、削除しました。
以前のバージョン
hidden属性をつけると他のMemberやWebUIから関数の存在を隠すことができます。 Client::funcEntries()でその関数の存在を確認したりFunc::args()などでの情報の取得ができなくなります。 ただし関数の名前がわかっていれば他Memberからでも実行は可能です。
- C++ で設定できます。
- JavaScript 1.0.4 set()関数の4番目の引数にtrueを指定することでできます。
wcli.func("hoge").set(hoge, valType.float_, [ ... ], true);
- Python set()関数(デコレータの場合はfunc())の引数に指定することで設定できます。
wcli.func("hoge").set(hoge, return_type=float, args=[...], hidden=True)
FuncListener
呼び出されたとき実行する関数を登録する代わりに、呼び出されたかどうかを監視し任意のタイミングで値を返すということもできます。 特にCのFFIで関数ポインタが利用できない場合に代わりに使えます。
C++
- Since
- 1.5
wcli.funcListener("hoge").listen();
で待ち受けを開始し、func.set()と同様関数が登録され他クライアントから見られるようになります。 (listen()自体は関数呼び出しを待機することはありません)
引数を受け取りたい場合は
wcli.funcListener("hoge").listen(3);
のように引数の個数を指定するか、または
wcli.funcListener("hoge").setArgs({...}).listen();
とすると通常のfuncと同様引数のオプションを設定可能です。 (func.setArgs()はfunc.set()の後でしたが、funcListenerではlisten()の前に実行する必要があります。)
その後、任意のタイミングで
std::optional<webcface::CallHandle> handle = wcli.funcListener("hoge").fetchCall();
とすることで関数が呼び出されたかどうかを調べることができます。
- その関数がまだ呼び出されていない場合はstd::nulloptが返ります。
- 関数が呼び出された場合、 CallHandle::args() で呼び出された引数を取得できます。
- 各引数は ValAdaptor 型で取得でき、
asStringRef()
, asString()
, asBool()
, as<double>()
, 2.0 asWStringRef()
, asWString()
, asDouble()
, asInt()
, asLLong()
で型を指定して取得できます。
- (std::string, double, bool などの型にキャストすることでも値を得られます。)
- listen時に指定した引数の個数と呼び出し時の個数が一致しない場合、fetchCallで取得する前に呼び出し元に例外が投げられます (そのため引数の個数チェックをする必要はないです)
- 通常の関数のreturnの代わりに、
handle.respond()
で関数呼び出しの終了を表し、戻り値を返すことができます。
- またthrowの代わりに
handle.reject()
でエラーメッセージを返すことができます。
詳細は webcface::CallHandle (ver2.0で FuncCallHandle から CallHandle に名前変更)
C
wcfStatus wcfFuncListen(wcfClient *wcli, const char *field, const wcfValType *arg_types, int arg_size, wcfValType return_type)
関数呼び出しの待受を開始する
Definition func.cc:314
で待ち受けを開始し、wcfFuncSet() と同様関数が登録され他クライアントから見られるようになります。 (wcfFuncListen()自体は関数呼び出しを待機することはありません)
その後、任意のタイミングで
wcfStatus wcfFuncFetchCall(wcfClient *wcli, const char *field, wcfFuncCallHandle **handle)
関数が呼び出されたかどうかを確認
Definition func.cc:324
とすることで関数が呼び出されたかどうかを調べることができます。
- その関数がまだ呼び出されていない場合は
WCF_NOT_CALLED
が返ります。
- 関数が呼び出された場合
WCF_OK
が返り、handle->args
に引数が格納されます。
- listen時に指定した引数の個数と呼び出し時の個数が一致しない場合、fetchCallで取得する前に呼び出し元に例外が投げられます (そのため引数の個数チェックをする必要はないです)
- 通常の関数のreturnの代わりに、 wcfFuncRespond, (2.0 wcfFuncRespondW) で関数呼び出しの終了を表し、戻り値を返すことができます。
- 1.9 戻り値が不要な場合は
wcfFuncRespond(handle, NULL);
とします。
- または wcfFuncReject, (2.0 wcfFuncRejectW) でエラーメッセージを返すことができます。 (
wcfFuncReject(handle, NULL);
も可)
Python
- Since
- 2.2
wcli.funcListener("hoge").listen()
で待ち受けを開始し、func.set()と同様関数が登録され他クライアントから見られるようになります。 (listen()自体は関数呼び出しを待機することはありません)
引数を受け取りたい場合は
wcli.funcListener("hoge").listen(args=[...])
のように引数の個数分の Arg を指定してください。
その後、任意のタイミングで
handle = wcli.funcListener("hoge").fetch_call()
とすることで関数が呼び出されたかどうかを調べることができます。
- その関数がまだ呼び出されていない場合はNoneが返ります。
- 関数が呼び出された場合、 handle.args で呼び出された引数を取得できます。
- listen時に指定した引数の個数と呼び出し時の個数が一致しない場合、fetch_callで取得する前に呼び出し元に例外が投げられます (そのため引数の個数チェックをする必要はないです)
- 通常の関数のreturnの代わりに、
handle.respond()
で関数呼び出しの終了を表し、戻り値を返すことができます。
- またthrowの代わりに
handle.reject()
でエラーメッセージを返すことができます。
詳細は webcface.CallHandle
関数の情報の取得
関数の引数や戻り値の情報を取得できます。 他のデータ型と違ってデータをリクエストする機能はなく、 関数の情報はクライアントが関数を登録してsync()した時点で送られてきます。
- C++ Member::func() でFuncクラスのオブジェクトが得られ、 Func::returnType() や Func::args() で関数の引数や戻り値の情報を取得できます。
std::vector<webcface::Arg> args = wcli.member("foo").func("hoge").args();
ValType
引数や戻り値の型を表すenum
Definition val_adaptor.h:21
引数の情報については webcface::Arg を参照 また、戻り値型は webcface::ValType というenum型で得られます。
- JavaScript Member.func() でFuncクラスのオブジェクトが得られ、 Func.returnType や Func.args で関数の引数や戻り値の情報を取得できます。
const args = wcli.member("foo").func("hoge").args;
const returnType = wcli.member("foo").func("hoge").returnType;
引数の情報については Arg を参照
- Python Member.func() でFuncクラスのオブジェクトが得られ、 Func.return_type や Func.args で関数の引数や戻り値の情報を取得できます。
args = wcli.member("foo").func("hoge").args
return_type = wcli.member("foo").func("hoge").return_type
引数の情報については webcface.Arg を参照
Entry
Valueと同様、関数が存在するかどうかを取得することができます。 使い方は Value と同様なのでそちらを参照してください
関数の実行
他クライアントに登録された関数を呼び出すことができます。 (自分でsetした関数を自分で実行することも一応可能です)
引数を渡したり、戻り値またはエラーメッセージを取得することができます。
C++ Func::runAsync() で関数を呼び出し、完了を待たずに続行します。 戻り値として AsyncFuncResult 2.0 Promise クラスのオブジェクトが返り、後から関数の戻り値や例外を取得できます。
2.0 Promiseでは以下のメソッドが使用可能です。
- reached(): 関数呼び出しのメッセージが相手のクライアントに到達したらtrue、それまでの間はfalseです。
- waitReach(), waitReachFor(), waitReachUntil(): reached()がtrueになるまで待機します。 For, Until の場合はタイムアウトを指定します。
- found(): reached()がtrueになった後、相手のクライアントが関数の実行を開始したらtrue、指定したクライアントまたは関数が存在しなかった場合falseです。
- reached()がfalseの間はfalseです。
- runAsync呼び出し時にクライアントがサーバーに接続していなかった場合は、関数呼び出しメッセージを送信することなく即座にfalseになります
- finished(): 関数の実行が完了し戻り値かエラーメッセージを受け取ったらtrue、それまでの間はfalseです。
- waitFinish(), waitFinishFor(), waitFinishUntil(): finished()がtrueになるまで待機します。 For, Until の場合はタイムアウトを指定します。
- response(): 関数の戻り値です。 webcface::ValAdaptor 型で返り、
asStringRef()
, asString()
, asWStringRef()
, asWString()
, asBool()
, asDouble()
, asInt()
, asLLong()
またはstatic_castにより型変換できます。
- rejection(), rejectionW(): 関数が例外を返した場合そのエラーメッセージを表す文字列です。 またその場合 isError() がtrueになります。
Promise res = wcli.member("foo").func("hoge").runAsync(1, "aa");
res.waitReach();
if(res.found()){
res.waitFinish();
if(res.isError()){
}else{
}
}else{
}
- Warning
- 2.0 上の例のようにwaitReach(), waitFinish() などで結果が返ってくるまで待機することができますが、 これらが結果を受信するためには Client::sync() が必要なため、別スレッドでsync()が呼ばれていなければデッドロックします。
onReach()
, onFinish()
で値が返ってきたときに実行されるコールバックを設定することができます。
- 引数にはそのPromise自身が渡されますが、(キャプチャするなどして)必要なければ引数なしの関数も設定可能です
- コールバックは Client::sync() の中から呼び出されます。
Promise res = wcli.member("foo").func("hoge").runAsync(1, "aa");
res.onReach([](Promise res){
if(res.found()){
}else{
}
});
res.onFinish([](Promise res){
if(res.isError()){
}else{
}
});
- Note
- onReach, onFinish を設定した時点ですでに関数の実行が完了していた場合は、そのときにコールバックが呼ばれます。 したがってコールバックはどの状況で設定したとしても必ず1回呼ばれます。 (呼ばれたあとにコールバックを再設定したりしても2度目が呼ばれることはありません)
C wcfFuncRunAsync, (2.0 wcfFuncRunAsyncW) で関数を呼び出し、完了を待たずに続行します。 受け取った wcfPromise を使って、 wcfFuncGetResult, (2.0 wcfFuncGetResultW) 後から関数の戻り値や例外を取得できます。
};
wcfStatus wcfDestroy(void *ptr)
wcfの関数から取得したポインタのデータを破棄
Definition client.cc:105
wcfStatus wcfFuncGetResult(wcfPromise *async_res, wcfMultiVal **result)
非同期で呼び出した関数の実行結果を取得
Definition func.cc:277
wcfStatus wcfFuncRunAsync(wcfClient *wcli, const char *member, const char *field, const wcfMultiVal *args, int arg_size, wcfPromise **async_res)
関数を非同期で呼び出す
Definition func.cc:266
wcfMultiVal wcfValS(const char *value)
文字列型のwcfMultiValを構築
Definition func.cc:251
void wcfPromise
Definition def_types.h:15
- (ver1.11まで wcfAsyncFuncResult 型でしたが ver2.0で wcfPromise に名前変更しました)
- 関数の実行がまだ完了していなければwcfFuncGetResultは
WCF_NOT_RETURNED
を返します。
- 完了していれば、wcfFuncGetResultは
WCF_OK
を返し、結果が wcfMultiVal 型で取得できます。
- このとき wcfPromise オブジェクトは破棄され使えなくなります (再度 wcfFuncGetResult を呼ぶことはできません)
- 1.7 また、受け取った wcfMultiVal オブジェクトは、不要になったら wcfDestroy で破棄してください。
- 2.0 戻り値を取得する必要がない場合は、 wcfDestroy でwcfPromiseも破棄することができます。
wcfFuncWaitResult, (2.0 wcfFuncWaitW) は関数の実行が完了し結果が返ってくるまで待機します。
- Warning
- 2.0 wcfFuncWaitResult() が結果を受信するためには wcfSync() が必要なため、別スレッドでwcfSync()が呼ばれていなければデッドロックします。
JavaScript
- Note
- 1.8 C++の Promise 型に合わせて名前変更しました。 以前の名前もまだ使えます。
Func.runAsync() で関数を呼び出すと、戻り値として AsyncFuncResult FuncPromise クラスのオブジェクトが返り、後から関数の戻り値や例外を取得できます。
AsyncFuncResult FuncPromise からは started reach と result finish が取得できます。 いずれもPromise型で、awaitで待機したり、then()とcatch()でコールバックを設定できます。
- reach (started) は対象の関数が存在して実行が開始したときにtrueになり、指定したクライアントまたは関数が存在しなかった場合falseとなります。
- 1.8 runAsync呼び出し時にクライアントがサーバーに接続していなかった場合は、関数呼び出しメッセージを送信することなく即座にfalseが返ります
- finish (result) は実行が完了したときに返ります。関数の戻り値を返すか、または発生した例外のメッセージを含むErrorでrejectします。
- 1.8 Rejectする値は常にError型になっています。 (1.7以前は関数がthrowしたオブジェクトをそのまま返していた)
import { FuncPromise } from "webcface";
const res: FuncPromise = wcli.member("foo").func("hoge").runAsync(1, "aa");
res.reach.then((found: boolean) => {
if (found) {
// 関数hogeが存在し、実行が開始された
} else {
// 関数hogeが存在しないか未接続で呼び出し失敗
}
});
res.finish.then((ret: number | boolean | string) => {
// ret が戻り値
}).catch((e) => {
// (e as Error).message がエラーメッセージ
});
Python Func.run_async() で関数を呼び出すと、 戻り値として AsyncFuncResult 2.0 Promise クラスのオブジェクトが返り、 後から関数の戻り値や例外を取得できます。
2.0 Promiseでは以下のメソッドが使用可能です。
- reached: 関数呼び出しのメッセージが相手のクライアントに到達したらTrue、それまでの間はFalseです。
- wait_reach(): reached がTrueになるまで待機します。 timeoutを指定することもできます。
- found: reachedがTrueになった後、相手のクライアントが関数の実行を開始したらTrue、指定したクライアントまたは関数が存在しなかった場合Falseです。
- reached がFalseの間はFalseです。
- run_async呼び出し時にクライアントがサーバーに接続していなかった場合は、関数呼び出しメッセージを送信することなく即座にFalseになります
- finished: 関数の実行が完了し戻り値かエラーメッセージを受け取ったらTrue、それまでの間はFalseです。
- wait_finish(): finished()がTrueになるまで待機します。 timeoutを指定することもできます。
- response: 関数の戻り値です。 int, float, bool, str型のいずれかで返ります
- rejection: 関数が例外を返した場合そのエラーメッセージを表す文字列です。 またその場合 is_error がTrueになります。
res = wcli.member("foo").func("hoge").run_async(1, "aa")
res.wait_reach()
if res.found:
res.wait_finish()
if res.is_error:
else:
else:
関数hogeが存在しないか未接続で呼び出し失敗
- Warning
- 2.0 上の例のようにwait_reach(), wait_finish() などで結果が返ってくるまで待機することができますが、 これらが結果を受信するためには Client.sync() が必要なため、別スレッドでsync()が呼ばれていなければデッドロックします。
on_reach()
, on_finish()
で値が返ってきたときに実行されるコールバックを設定することができます。
- 引数にはそのPromise自身が渡されます
- eventのコールバックと同様、デコレータとして使ってコールバックを設定することもできます。
- コールバックは Client.sync() の中から呼び出されます。
res = wcli.member("foo").func("hoge").run_async(1, "aa")
@res.on_reach
def on_reach(res: Promise):
if res.found:
else:
@res.on_finish
def on_finish(res: Promise):
if res.is_error:
else:
- Note
- on_reach, on_finish を設定した時点ですでに関数の実行が完了していた場合は、そのときにコールバックが呼ばれます。 したがってコールバックはどの状況で設定したとしても必ず1回呼ばれます。 (呼ばれたあとにコールバックを再設定したりしても2度目が呼ばれることはありません)
Func.run() は関数を呼び出し、結果が返ってくるまで待機します。 例外が返ってきた場合はRuntimeErrorを、また呼び出しに失敗した場合は webcface.FuncNotFoundError をraiseします。
result = wcli.member("foo").func("hoge").run(1, "aa")
- wait_reach(), wait_finish() と同様 Client.sync() が呼ばれていないとデッドロックするので注意してください。
Funcオブジェクトに()と引数をつけて直接呼び出すことでも同様に実行できます。 (Func.__call__
)
AsyncFuncResult.started と result (ver2.0からdeprecated)
C++
AsyncFuncStarted::started と AsyncFuncResult::result はstd::shared_futureであり、取得できるまで待機するならget(), ブロックせず完了したか確認したければwait_for()などが使えます。
- started は対象の関数が存在して実行が開始したときにtrueになり、指定したクライアントまたは関数が存在しなかった場合falseとなります。
- 2.0 runAsync呼び出し時にクライアントがサーバーに接続していなかった場合は、関数呼び出しメッセージを送信することなく即座にfalseになります
- result は実行が完了したときに返ります。関数の戻り値、または発生した例外の情報を含んでいます。
- 実行した関数が例外を返した場合はresult.get()がstd::runtime_errorを投げます。
- 2.0 started.get() や result.get() はver2.0以降デッドロックする可能性があります。 詳細は上に書かれている waitReach(), waitFinish() の注意を参照してください
Python AsyncFuncResultからは started と result が取得できます。
- started は対象の関数が存在して実行が開始したときにtrueになり、指定したクライアントまたは関数が存在しなかった場合falseとなります。
- result は実行が完了したときに返ります。関数の戻り値、または発生した例外の情報を含んでいます。
startedとresultは取得できるまで待機するgetterです。例外の場合はresultの取得時に投げます。 また、取得可能になったかどうかをstarted_readyとresult_readyで取得できます。 詳細は webcface.AsyncFuncResult を参照
CallbackListを返す AsyncFuncResult::onStarted(), onResult() (C++ ver1.11)
1.11 onStarted()
, onResult()
で値が返ってきたときに実行されるイベントが取得でき、コールバックを設定することができます。 (eventpp::CallbackList 型の参照で返ります)
AsyncFuncResult res = wcli.member("foo").func("hoge").runAsync(1, "aa");
res.onStarted().append([](bool started){
std::cout << "func hoge() " << started ? "started" : "not started" << std::endl;
});
res.onResult().append([](std::shared_future<webcface::ValAdaptor> result){
try{
double ans = result.get();
}catch(const std::exception &e){
std::cout << e.what() << std::endl;
}
});
C++の Func::run(), Cの wcfFuncRun() (ver2.0からdeprecated)
C++ Func::run() で関数を実行できます。引数を渡すこともでき、戻り値もそのまま返ってきます。 他クライアントの関数も同様にrun()で実行させることができます。
実行した関数が例外を投げた場合、また引数の個数が一致しない場合などはrun()が例外を投げます。
対象のクライアントと通信できない場合、また指定した関数が存在しない場合は webcface::FuncNotFoundError を投げます。
double ans = wcli.member("foo").func("hoge").run(1, "aa");
Funcオブジェクトに()と引数をつけて直接呼び出すことでも同様に実行できます。 (Func::operator()
)
戻り値は webcface::ValAdaptor 型で返ります。 整数、実数、bool、stringにキャストできます。
1.10 また、明示的にキャストするなら asStringRef()
(const参照), asString()
, asBool()
, as<整数or実数型>()
も使えます。
2.0 asWStringRef()
, asWString()
, asDouble()
, asInt()
, asLLong()
も使えます。
- Warning
- start()を呼んで通信を開始する前にrun()を呼び出してしまうとデッドロックします。
C
};
int ret =
wcfFuncRun(wcli_,
"a",
"b", args, 3, &ans);
wcfStatus wcfFuncRun(wcfClient *wcli, const char *member, const char *field, const wcfMultiVal *args, int arg_size, wcfMultiVal **result)
関数を呼び出す
Definition func.cc:256
関数が存在しない場合WCF_NOT_FOUND
を返します。 関数が例外を投げた場合WCF_EXCEPTION
を返し、ret->as_strにエラーメッセージが入ります。
1.7 結果が格納されているポインタは、不要になったら wcfDestroy(ans); で破棄してください。
- Warning
- wcfStart()を呼んで通信を開始する前にwcfFuncRun()を呼び出してしまうとデッドロックします。