LS2CAPI : 参照渡しか値渡しか
- バックナンバー -
1. OSLoadProgramを呼んでみるサンプル
2. OSLoadProgramのサンプルを理解する
3. C API はnnotes.dllから呼ばれている
4. 参照渡しか値渡しか
5. 型を変換する
6. 構造体を定義する
7. OSLoadString を使ってみよう
さて、LotusScriptから C API関数を呼ぶ話は興味がある方は興味を持って頂けると思うのですが、興味がない方には全然興味が無いと思うので、書いていて難しいのですが、書き始めてしまった以上こつこつ書いていこうと思います。
今日も引き続きAPI関数への変換の話をしようと思うのですが、LotusScriptではあまり意識する事はありませんが、Cの関数では関数の引数として参照渡しと値渡しがあります。 値渡しであれば、関す内で引数をいくら書き換えても実行後戻ってきたときには引数の値は呼び出したときの値に戻っています。 参照渡しでは書き換えられた値を使用することが出来るのです。 言うまでもなく、LotusScriptなどではすべて参照渡しで引数が処理されています。
ここを区別するにはデザイナーヘルプの「引数の参照渡しと値渡し 」なども参考にして頂きたいのですが、関数ごとにその引数が使われるかを考えなくてはいけません。単純にポインター引数か否か?と言うだけでは判断できない点もあるので都度よく考えるしかありませんが、実際的にはこの後とりあげる型変換の話と同じで、変換方法を覚えてしまう方法がいいかもしれません。
たとえば、C APIでは文書のIDとして、引数でそのまま渡せるNOTTEID (DWORD)が好んで使われます。このNOTEIDは値渡しされていることが多いのですが、関数の戻り値として引数にNOTEIDが使用される場合には参照渡しになるのでByValをつけることは出来ません。
また、C言語ではString型はchar型の配列を使用しますが、これは値渡しで使うことが多いように思えます。私自身はもうこれは例外ルールのような理解をしているのですが、デザイナーヘルプでは以下のように記載されています。
と言うわけで普通にNULLで終わる文字列を使う分には値渡しの事が多いのです。
OSLoadProgram() のサンプルでは以下のように宣言していました。
Declare Function OSLoadProgram Lib "nnotes.dll" _
(Byval filename As String, Byval FileDir As String, Byval argv As String, Byval flags As Integer) As Integer
Stringの部分は例によってすべてByVal を付けているのは上述したヘルプの記載に基づいています。
最後のFlagの部分は実はByValを付けなくても動いたのですが、C API リファレンスを見てもここはポインターでも何でもないWORD型の値を値渡ししているので、ByVal を付けた方がよいのではないかと思います。
上手く説明できていない部分も多いのですが、LotusScriptではあまり意識しない引数の値渡し、参照渡しですが、C APIの呼び出しの際には慎重に考えていく必要があります。
1. OSLoadProgramを呼んでみるサンプル
2. OSLoadProgramのサンプルを理解する
3. C API はnnotes.dllから呼ばれている
4. 参照渡しか値渡しか
5. 型を変換する
6. 構造体を定義する
7. OSLoadString を使ってみよう
さて、LotusScriptから C API関数を呼ぶ話は興味がある方は興味を持って頂けると思うのですが、興味がない方には全然興味が無いと思うので、書いていて難しいのですが、書き始めてしまった以上こつこつ書いていこうと思います。
今日も引き続きAPI関数への変換の話をしようと思うのですが、LotusScriptではあまり意識する事はありませんが、Cの関数では関数の引数として参照渡しと値渡しがあります。 値渡しであれば、関す内で引数をいくら書き換えても実行後戻ってきたときには引数の値は呼び出したときの値に戻っています。 参照渡しでは書き換えられた値を使用することが出来るのです。 言うまでもなく、LotusScriptなどではすべて参照渡しで引数が処理されています。
ここを区別するにはデザイナーヘルプの「引数の参照渡しと値渡し 」なども参考にして頂きたいのですが、関数ごとにその引数が使われるかを考えなくてはいけません。単純にポインター引数か否か?と言うだけでは判断できない点もあるので都度よく考えるしかありませんが、実際的にはこの後とりあげる型変換の話と同じで、変換方法を覚えてしまう方法がいいかもしれません。
たとえば、C APIでは文書のIDとして、引数でそのまま渡せるNOTTEID (DWORD)が好んで使われます。このNOTEIDは値渡しされていることが多いのですが、関数の戻り値として引数にNOTEIDが使用される場合には参照渡しになるのでByValをつけることは出来ません。
また、C言語ではString型はchar型の配列を使用しますが、これは値渡しで使うことが多いように思えます。私自身はもうこれは例外ルールのような理解をしているのですが、デザイナーヘルプでは以下のように記載されています。
文字列を引き渡す
文字列が参照渡しされる場合、LotusScript は、文字列のコピーへの 4 バイトのポインタをメモリ内で割り当てられた内部バッファに渡します。LotusScript に C 関数が明確に記述されていない限り、C 関数はこのバッファの内容を安全に変更できません。
文字列が値渡しされる場合、LotusScript は、null で終わる文字列 (C 関数で想定されます) に 4 バイトのポインタを渡します。C 関数はこの文字列を変更できますが、その長さを伸ばすことはできません。文字列への変更は、関数からの戻り値としてスクリプトの変数に反映されます。文字列以外へのポインタを渡す場合は、パラメータを参照渡しします。
と言うわけで普通にNULLで終わる文字列を使う分には値渡しの事が多いのです。
OSLoadProgram() のサンプルでは以下のように宣言していました。
Declare Function OSLoadProgram Lib "nnotes.dll" _
(Byval filename As String, Byval FileDir As String, Byval argv As String, Byval flags As Integer) As Integer
Stringの部分は例によってすべてByVal を付けているのは上述したヘルプの記載に基づいています。
最後のFlagの部分は実はByValを付けなくても動いたのですが、C API リファレンスを見てもここはポインターでも何でもないWORD型の値を値渡ししているので、ByVal を付けた方がよいのではないかと思います。
上手く説明できていない部分も多いのですが、LotusScriptではあまり意識しない引数の値渡し、参照渡しですが、C APIの呼び出しの際には慎重に考えていく必要があります。
コメント
Re: LS2CAPI : 参照渡しか値渡しか
OSLoadString で、文字列長のバッファとして、sizeof() を利用しているのですが、LotusScript の場合、代替できる方法はありますか?
2009-11-28 02:18 通りすがり URL 編集
Re: LS2CAPI : 参照渡しか値渡しか
>String については、lmbcs で渡すと OSTranslate を使わずにすむので、扱いが楽になりますよ。お試しあれ。
これは、正しくは、
Declare Function OSLoadProgram Lib "nnotes.dll" _
(Byval filename As LMBCS String, Byval FileDir As LMBCS String, Byval argv As LMBCS String, Byval flags As Integer) As Integer
↑を指して書きました。
2009-11-28 02:23 通りすがり URL 編集
ありがとうございます
こういうコメントが頂けるのはブログをやっていて、自分も勉強になるのでありがたいなあ・・・と思います。
確かにOSTranslateで変換すればいいのですが、私のサンプルではダブルバイトをパスに渡す事を想定していませんでした。
Tipsと言うよりサンプルは本来そう書くべきだったと思います。
W32 APIとかではUNICODE宣言とかも使えるのかなあ・・・と思っていますがこれに関しては経験がないので分かりませんが。。
2009-11-28 11:54 長島 広隆 URL 編集