2013年12月31日火曜日

【なでしこ】nako_comm.dll

2013年も今日で終わりか!!Σ( ̄口 ̄;;。ってことで結局あまり時間が
とれずにデバッグ出来なかったけど、取りあえず現状の"nako_comm.dll"を公開
します。

上記のリンクを辿るとnako_comm.7zをDL出来ますので、適当なところに解凍
します。

------ここから------
\nako_comm
|   debug.c
|   dll_comm_funcs.c
|   dll_comm_funcs.h
|   dnako_callback_funcs.c
|   dnako_import.c
|   dnako_import.h
|   dnako_import_def.h
|   dnako_import_types.c
|   dnako_import_types.h
|   dnako_plugin_body.c
|   log.txt
|   nako_comm.txt
|  
\---nako_dll_base
    |   dnako_import.def
    |   nako_dll_base.sln
    |   nako_dll_base.vcxproj
    |   nako_dll_base.vcxproj.user
    |  
    \---dll
            nako_comm_d.dll
            nako_comm_r.dll

 ------ここまで------

\nako_dll_base\dllの中に2つDLLが入ってます。「_d」がデバッグ版、
「_r」がリリース版でVC++でコンパイルしてます。使用の際は、それぞれ
「nako_comm.dll」にリネーム後、なでしこの\plug-insフォルダに
コピーして使ってください。


再コンパイルする場合には\nako_dll_base\nako_dll_base.slnをクリックして
VC++(Express)を起動して、コンパイルしてください。


含まれる命令(関数)仕様は以下の通りですが、あんまりデバッグ
してませんので、今回のものはDLLのサンプル程度に参照して
ください。来年(暇があったら)デバッグします(^^;。

------ここから------

■関数仕様

・バイト確保
    書式:バイト確保([int]バイト数、[int]初期値)
    戻値:[int]ハンドル
    説明:バイト数に1,2,4の何れかを指定して、変数を確保し、初期値を
       代入する。以降、戻り値のハンドルを使用して、値を読み書き
          出来る。
         
          確保されるメモリ領域は内部でunsignedで扱われる。この値は
          なでしこ側から見るとグローバルな領域になるので、関数内等
          ローカルスコープから本関数をコールした場合も、変数自体は
          グローバルに確保されていることに注意すること(つまり、
          なでしこの関数を抜けても、変数領域は解放されない)。
         
          確保が成功した場合には0以上の整数が、失敗した場合には-1
          が返される。使用が終了した場合はハンドルを解放すること。

・バイト読込
    書式:バイト読込([int]ハンドル)
    戻値:[int]変数値
    説明:バイト確保命令で取得したハンドルの、現在の値を取得する。
       戻り値は整数型になる。無効なハンドル値を指定した場合には
          常に0が返される。
         
・バイト書込
    書式:バイト書込([int]ハンドル、[int]値)
    戻値:[int]結果
    説明:バイト確保命令で取得したハンドルに対して、指定した値を
       書き込む。書き込める値の範囲は確保されている領域サイズに
          より異なり、範囲外の値を指定した場合にはエラーとなる。
         
          書込が成功した場合には0が、失敗した場合には-1が返される。

・エンディアン変換
    書式:エンディアン変換([int]ハンドル)
    戻値:[int]結果
    説明:バイト確保命令で取得したハンドルに対応する値のエンディアン
       変換を実施する。変換後の値はハンドル対応値に上書きされる。
         
          成功した場合は0が、無効なハンドルを指定した場合は-1が
          返される。

・バッファ確保
    書式:バッファ確保([int]サイズ)
    戻値:[int]ハンドル
    説明:メモリを動的に確保して、そのハンドルを返す。成功した場合、
       0以上のハンドル値が、失敗した場合には-1が返される。
         
          なお、メモリは動的に確保されているので、使用後はかならず
          ハンドルの解放を実施して確保されたメモリ領域を解放する
          こと。

・バッファクリア
    書式:バッファクリア([int]ハンドル、[int]クリア値)
    戻値:[int]結果
    説明:バッファ確保命令で取得したハンドルの領域をクリア値を用いて
       クリアする。クリア値には0~255(0xFF)までの1byte値を指定
          する。
         
          成功した場合は0が、無効なハンドル、クリア値を指定した
          場合は-1が返される。

・バッファコピー
    書式:バッファコピー([int]元ハンドル、[int]先ハンドル、[int]サイズ)
    戻値:[int]結果
    説明:既に確保されているコピー元ハンドルから、コピー先ハンドルに
       データをコピーする。先ハンドルはバッファでなくては
          ならないが、元ハンドルについてはバッファ、もしくは
          上記バイト確保命令で取得したハンドルでも良い。
         
          成功した場合は0が、無効なハンドルを指定した場合には-1が
          返される。

・バッファ読込
    書式:バッファ読込([int]ハンドル、[int]オフセット)
    戻値:[int]読込データ
    説明:既に確保されているメモリ領域(ハンドル)の、所定のオフセット
       位置から、1byteのデータを取得して返す。
         
          無効な引数を指定した場合には0が返される。

・バッファ書込
    書式:バッファ書込([int]ハンドル、[int]オフセット、[int]データ)
    戻値:[int]結果
    説明:既に確保されているメモリ領域(ハンドル)の、所定のオフセット
       位置に、1byteのデータを書き込む。データには0~255の値を
          指定する。
         
          成功した場合には0が、無効な引数を指定した場合には-1が
          返される。

・リングバッファ確保
    書式:バッファ確保([int]サイズ)
    戻値:[int]ハンドル
    説明:メモリを動的に確保して、そのハンドルを返す。成功した場合、
       0以上のハンドル値が、失敗した場合には-1が返される。
         
          なお、メモリは動的に確保されているので、使用後はかならず
          ハンドルの解放を実施して確保されたメモリ領域を解放する
          こと。
         
          「バッファ確保」と処理内容は一緒だが、以降このバッファは
          リングバッファとして扱われる。

・リングバッファ読込
    書式:リングバッファ読込([int]ハンドル、[int]先ハンドル、[int]サイズ)
    戻値:[int]サイズ
    説明:確保されているリングバッファハンドルから、サイズ分を読み
         込んで先ハンドル(バッファ)に書き込む。読み込めるサイズは
          コピー先のバッファサイズに依存し、バッファサイズ以上の
          データは読み込まない。読み込めたサイズは戻り値として返される。
         
          リングバッファなので、読み込みの開始位置は現在の読込位置
          となり、読み込んだサイズ分は以降書込可能領域となる。
         
          引数が不正な場合等、エラーの場合は-1が返される。

・リングバッファ書込
    書式:リングバッファ書込([int]ハンドル、[int]元ハンドル、[int]サイズ)
    戻値:[int]サイズ
    説明:作成済みの元ハンドル(バッファ)からサイズ分読み込んで、
       確保されているリングバッファハンドルに対して書き込む。
          書き込めるサイズは元ハンドルのサイズに依存し、それ以上の
          サイズを指定した場合は、書き込めるだけ書き込む。
          (データがある分だけ書き込む)。書き込めたサイズが戻り値
          として返される。
         
          書き込み位置はリングバッファ中の書き込み可能な領域の先頭
          からとなり、書き込んだ分は以降読込可能となる。書き込む前に
          空き領域を知りたい場合には「リングバッファ空きサイズ」
          命令でサイズを取得出来る。
         
          引数が不正な場合等、エラーの場合は-1が返される。

・リングバッファ読込サイズ
    書式:リングバッファ読込サイズ([int]ハンドル)
    戻値:[int]読込可能サイズ
    説明:確保されているリングバッファハンドルの、現在読み込める
       データサイズを返す。
         
          引数が不正な場合等、エラーの場合は-1が返される。

・キュー作成
    書式:キュー作成(#引数なし)
    戻値:[int]ハンドル
    説明:空のキューを作成して、そのハンドルを返す。キューに対しては
       本ライブラリで生成出来るハンドルを追加・取得出来る(FIFO)。
         
          成功した場合にはハンドル値が、失敗した場合には-1が返される。

・キュー追加
    書式:キュー追加([int]キュー、[int]ハンドル)
    戻値:[int]結果
    説明:指定のキューハンドルに、ハンドルを追加する。
   
       成功した場合は0が、失敗した場合は-1が返される。

・キュー取得
    書式:キュー取得([int]キュー)
    戻値:[int]ハンドル
    説明:指定されたキューから、先頭の1要素を取得して返す。
   
       成功した場合にはハンドル値が、失敗した場合には-1が返される。

・キュー要素数取得
    書式:キュー要素数([int]ハンドル)
    戻値:[int]要素数
    説明:指定されたキューに繋がれているハンドル数(要素数)を
       返す。失敗した場合には-1が返される。

・スタック作成
    書式:スタック作成(#引数なし)
    戻値:[int]ハンドル
    説明:空のスタックを作成して、そのハンドルを返す。スタックに対しては
       本ライブラリで生成出来るハンドルを追加・取得出来る(LIFO)。
         
          成功した場合にはハンドル値が、失敗した場合には-1が返される。

・スタック追加
    書式:スタック追加([int]スタック、[int]ハンドル)
    戻値:[int]結果
    説明:指定のスタックハンドルに、ハンドルを追加する。
   
       成功した場合は0が、失敗した場合は-1が返される。

・スタック取得
    書式:スタック取得([int]スタック)
    戻値:[int]ハンドル
    説明:指定されたスタックから、末尾の1要素を取得して返す。
   
       成功した場合にはハンドル値が、失敗した場合には-1が返される。

・スタック要素数取得
    書式:スタック要素数([int]ハンドル)
    戻値:[int]要素数
    説明:指定されたスタックに繋がれているハンドル数(要素数)を
       返す。失敗した場合には-1が返される。

・バイナリオープン
    書式:バイナリオープン([str]ファイル名、[int]モード)
    戻値:[int]ハンドル
    説明:ファイル名で指定されたファイルを、モードで指定された方法で
       オープンする。モードには0,1,2,3の何れかを指定し、意味は
          以下のとおり。

           0 : 読込専用
           1 : 書込専用
           2 : 読み書き
           3 : 追記
           
         ファイルは常にバイナリとしてオープンされる。テキストモード
          で扱いたい場合には、なでしこの組み込み命令を使用すると良い。

         成功すると0以上のハンドルが返される。失敗した場合には-1が
          返される(ファイルがない、モードが範囲外など)

・バイナリ読込
    書式:バイナリ読込([int]ハンドル、[int]先ハンドル、[int]サイズ)
    戻値:[int]サイズ
    説明:バイナリオープンされているハンドルから、サイズ分を読み
         込んで先ハンドル(バッファ)に書き込む。読み込めるサイズは
          コピー先のバッファサイズに依存し、バッファサイズ以上の
          データは読み込まない。読み込めたサイズは戻り値として
          返される。
         
          読み込み開始位置は現在の開始位置で、読み込む毎にオフセット
          がプラスされる。現在の開始位置はバイナリ位置取得命令で
          取得出来、位置の変更はバイナリシーク命令で可能である。
         
          引数が不正な場合等、エラーの場合は-1が返される。

・バイナリ書込
    書式:バイナリ書込([int]ハンドル、[int]元ハンドル、[int]サイズ)
    戻値:[int]サイズ
    説明:作成済みのバッファ(元ハンドル)からサイズ分読み込んで、
     バイナリオープンされているハンドルに対して書き込む。
          書き込めるサイズは元ハンドルのサイズに依存し、それ以上の
          サイズを指定した場合は、書き込めるだけ書き込む。
          (データがある分だけ書き込む)。書き込めたサイズが戻り値
          として返される。
         
          書込開始位置は、書込専用、読み書き用にオープンしている場合は
          ファイルの先頭から開始し、書き込む毎にオフセットがプラスされ
          る。既存ファイルの場合は一旦ファイルが消去されるので注意する
          こと。追記モードの場合はファイルの終端から書込が開始される。
         
          引数が不正な場合等、エラーの場合は-1が返される。

・バイナリシーク
    書式:バイナリシーク([int]ハンドル、[int]オフセット)
    戻値:[int]オフセット
    説明:バイナリオープンされているハンドルの読み込み・書込開始
       位置をオフセットの値に設定する。オフセットは0以上の
          値で、ファイルサイズ以上の値を設定した場合には、ファイルの
          末尾となる。
         
          成功した場合にはオフセット値が、失敗した場合には-1が
          返される。

・バイナリ位置取得
    書式:バイナリ位置取得([int]ハンドル)
    戻値:[int]位置
    説明:バイナリオープンされているハンドルの、現在開始位置を
       返す。引数が不正だった場合には-1が返される。

・ビットチェック
    書式:ビットチェック([int]ハンドル、[int]パターン)
    戻値:[int]結果
    説明:対象となるハンドルと、パターンを指定して、パターンビット
       が対象に含まれているかチェックする。対象はバイト確保
          されたハンドルであること。
         
          パターンが含まれている場合には1(TRUE)が、含まれていない
          場合は0(FALSE)が返される。引数が不正な場合には0が返される。

・ビットセット
    書式:ビットセット([int]対象、[int]パターン)
    戻値:[int]結果
    説明:対象のハンドル値に、パターンビットを設定する。対象は
         バイト確保されたハンドルを指定する。
         
          成功した場合には0が、引数に不正があった場合には-1が
          返される。

・ビットクリア
    書式:ビットクリア([int]対象、[int]パターン)
    戻値:[int]結果
    説明:対象のハンドル値の、パターンで指定されるビットをクリア
       する。対象はバイト確保されたハンドルであること。
         
          成功した場合には0が、引数に不正があった場合には-1が
          返される。

・ソケットオープン
    書式:ソケットオープン([int]タイプ)
    戻値:[int]ハンドル
    説明:タイプを指定してソケットを作成(オープンする)。
       タイプには以下の何れかを指定する。
           
            0 : TCP
            1 : UDP
         
          成功した場合には0以上のハンドル値が返される。失敗
          した場合には-1が返される。

・ソケット接続待ち
    書式:ソケット接続待ち([int]ハンドル、[int]ポート)
    戻値:[int]ソケットハンドル
    説明:ソケットオープンで取得済のハンドルと、指定のポートを
          使って、TCPで相手が接続してくるのを待つ。
         
          成功した場合は新規のソケットハンドルが、失敗した場合は
          -1が返される。成功した場合、後述の「相手IPアドレス取得」
          命令を使用して、接続相手のアドレスを取得することが出来る。

・ソケット接続
    書式:ソケット接続([int]ハンドル、[str]相手のアドレス、[int]ポート)
    戻値:[int]結果
    説明:ソケットオープンで取得済のハンドルと、サーバ側のアドレス、
         ポートを指定してTCPで接続する。
         
          接続が成功した場合には0が、失敗した場合には-1が返される。

・TCP送信
    書式:TCP送信([int]ハンドル、[int]バッファ、[int]サイズ)
    戻値:[int]サイズ
    説明:ソケットオープンで取得済のハンドル、且つこのソケットで
       相手に接続している場合に、バッファで指定されるハンドル
          のデータをサイズ分送信する。バッファはバッファ確保で
          取得したハンドルを指定すること。
         
          成功した場合には送信出来たサイズが返される。失敗した
          場合には-1が返される。

・TCP受信
    書式:TCP受信([int]ハンドル、[int]バッファ)
    戻値:[int]サイズ
    説明:ソケットオープンで取得済のハンドル、且つこのソケットで
       相手に接続している場合に、バッファで指定されるハンドル
          にデータを受信する。

          成功した場合には受信出来たサイズが返される。失敗した
          場合には-1が返される。

・UDP送信
    書式:UDP送信([int]ハンドル、[int]バッファ、[str]相手アドレス、[str]ポート)
    戻値:[int]サイズ
    説明:ソケットオープンで取得済のハンドルと、送信対象のバッファ
       のハンドル、及び相手アドレスとポートを指定してデータを
          送信する。ソケットハンドルはUDPでオープンされていること。
         
          成功した場合には送信サイズが返さえる。失敗した場合には
          -1が返される。

・UDP受信
    書式:UDP送信([int]ハンドル、[int]バッファ、[str]ポート)
    戻値:[int]サイズ
    説明:ソケットオープンで取得済のハンドルと、受信データ書きこみ
       用のバッファハンドル、及びポートを指定してデータを受信
          する。
         
          成功した場合には受信出来たサイズが返される。失敗した
          場合には-1が返される。

・相手IPアドレス取得
    書式:相手IPアドレス取得([int]ハンドル)
    戻値:[str]相手IPアドレス(文字列)
    説明:ソケットハンドルを指定して、TCP通信で接続した相手のアドレス、
       及びUDP通信で受信した場合の相手のIPアドレスを文字列で返す。

・シリアルオープン
    書式:シリアルオープン([int]ポート、[int]ボーレート)
    戻値:[int]ハンドル
    説明:ポートとボーレートを指定して、シリアルポートをオープン
        する。ポート、ボーレート以外のパラメータは、
         
           データ  :8bit
            パリティ :なし
            ストップ :1bit
            フロー制御:なし
         
          となる。
         
          成功した場合は0以上のハンドル値が返される。失敗した場合は
          -1が返される。

・シリアル送信
    書式:シリアル送信([int]ハンドル、[int]バッファ、[int]サイズ)
    戻値:[int]サイズ
    説明:シリアルオープンで取得済のハンドル、及びバッファ確保した
         ハンドルを指定してサイズ分のデータを送信する。
         
          成功した場合には送信出来たサイズが、失敗した場合には-1が
          返される。

・シリアル受信
    書式:シリアル受信([int]ハンドル、[int]バッファ、[int]サイズ)
    戻値:[int]サイズ
    説明:シリアルオープンで取得済のハンドル、及びバッファ確保した
         ハンドルを指定してサイズ分のデータを受信する。

          成功した場合には受信サイズが、失敗した場合には-1が
          返される。

・シリアルデータサイズ
    書式:シリアルデータサイズ([int]ハンドル)
    戻値:[int]サイズ
    説明:シリアルオープンで取得済のハンドルで指定されるシリアル
       ポートに対して、そのバッファに受信されているデータ
          サイズを取得する。
         
          ここでのバッファとは上記バッファ確保したものではなく
          Windowsのシリアルドライバが保持している受信バッファで
          ある。

・ハンドルタイプ取得
    書式:ハンドルタイプ([int]ハンドル)
    戻値:[int]ハンドルタイプ
    説明:指定ハンドルの種別を取得する。戻り値は以下のとおり。
      
       -1 :エラー(使われてない、など)
        1 :バイト
        2 :バッファ(リングバッファ)
        4 :ファイル
        8 :キュー
       16 :スタック
       32 :ソケット
       64 :シリアルポート
      
・ハンドル解放
    書式:ハンドル解放([int]ハンドル)
    戻値:なし
    説明:取得したハンドルを解放する。対象がメモリの場合はメモリ
       が解放され、バイナリ(ファイル)やソケットの場合は
          それらがクローズされる。

------ここまで------

いや~、なんか色々入れすぎた感もありますが、使いこなせば
C言語に近い動作をさせられそう♪。ただ、この後別のアプリを
なでしこでざっと作ってみて、なでしこに足りない部分はこの手の
命令よりも、実はGUIかなあ…と思ってます。エディタの簡易GUI
構築環境…思ってたよりも使えなかったなあ( ̄へ ̄;。

来年はこのあたりの解決方法を検討しよう♪

2013年11月10日日曜日

【Buffalo】無線ルータと簡易NASの話

近所のJoshinが閉店セールとかやってたので行ってみたら、無線ルータが
アマゾンよりやすい値段で速攻で購入♪

旧:Buffalo WZR-HP-G301NH
新:Buffalo WZR-600DHP2

となって快適な無線LAN環境が出来上がるハズだったのに、問題発生。
まず、iPhone5/5Cは5GHz帯(802.11a/n)の掴みがあまりよろしく
ない。ルーターが2階にあるからなのかもしれないが、KindleFireHDの
方は流石に良くつかんでる。ってことで、iPhoneの方は2.4GHz帯で
しばらく運用。

もう一点はG301の方にも600DHP2の方にも簡易NAS機能がついてて
USBのHDDつなげられる様になっているけど、G301で使ってたHDDを
600DHP2の方につなぎ変えても認識しない(正確には認識はするけど
未フォーマットと言われる)。

Buffaloのルータについてる簡易NAS機能は、LinuxのXFSフォーマット
になってるけど、どうもG301のこのフォーマットが質が悪いみたいで
LinuxPCでも600DHP2でも認識しない。試しに再度G301に接続
し直してみると、これはちゃんと認識した。ってことで、再度G301を
復活させて、WInPC介して余ってたHDDにコピー。115GBのデータが
入ってたので、4時間ぐらいかかった…。

コピーし終わったら、NAS用のHDDを600DHP2側でXFSフォーマット。
これを試しにLinuxPFでマウントすると、ちゃんと認識する。WinPC
介して、今度は600DHP2上の簡易NASにHDDからデータコピーしようと
思ったら23時間とかでたのでヤメ。Linuxで認識するんだから、Linux上
でコピーすればいいやってことで、昨日つくったPuppyLinux5.7.1環境
でHDD→HDDのコピー。時間は表示されないけど、まあそこそこの
スピードでコピーしてくれてるから、3時間もあれば終わるかな。

これもBuffalo系の商品だけど、玄人志向の

KURO-DACHI/CLONE/U3

と言う商品に最近非常にお世話になってる。上記のHDD→HDDコピーも
これ一台をLinuxに繋げれば2ドライブ見えてコピーできるし、そもそも
PCがなくてもHDDのクローンが作れる。これでノートPCのHDDを
SSHDに交換した♪。

PuppyLinuxは150MBぐらいの容量があれば全部入るので、USBフラッシュ
メモリに入れて使ってる。ちょっと構成にクセはあるけど、何かカワイイ
からお気に入り(^^)。

ああ…本当はなでしこのプログラミングしようと思ってたのになあ…

2013年10月22日火曜日

【なでしこ】カレンダーを作ってみる

今、gnakoを使って少し大きめのアプリ書いてるんですが…。
gnakoの問題点が色々分かって、やっぱりGUIのエディタは
別のモノを使ったほうがいいんじゃないかと。通信DLLは
大体出来てるので、この辺り片付けたら、次はWinAPIを
もうちょっとダイレクトに触れるDLLなりexeなり作ろうかなあ。

さて、今回は「少し大きめのアプリ」でも使ってるカレンダー
機能のお話し。なでしこのくみこみ関数使ってある程度は
できるんですが、GUI用に使うならこれぐらいは欲しいかなあ
と言う部分を補完。

------ここから------

 ■GRP年月日
 ・{整数}年
  ・{整数}月
  ・{整数}日数
  ・日
  ・日数設定~
   日数=月日数判断(年、月)
  ・曜日設定~
  日数回
     年月日=「{年}」&「/」&「{月}」&「/」&「{回数}」
   日\回数=年月日の曜日

●二月日数判断(Yの)
 もしYを4で割った余り=0ならば
   もしYを100で割った余り=0ならば
     もしYを400で割った余り=0ならば
       日数=29
      違えば
       日数=28
    違えば
     日数=29
  違えば
   日数=28

 日数で戻る

●月日数判断(Y、M)
 Mで条件分岐
   1ならば
     日数=31
    2ならば
     日数=Yの二月日数判断
  3ならば
     日数=31
  4ならば
     日数=30
  5ならば
     日数=31
  6ならば
     日数=30
  7ならば
     日数=31
  8ならば
     日数=31
  9ならば
     日数=30
  10ならば
     日数=31
  11ならば
     日数=30
  12ならば
     日数=31
    違えば
     日数=0
   
  日数で戻る

------ここまで------

こんなもんでしょうか。「■GRP年月日」がカレンダー情報を
保持していて、要素「日」は配列です。「年」と「月」を設定して
「日数設定」メソッドと、「曜日設定」メソッドを呼べば、「日数」
にその月が何日あるかと、「日」にそれぞれの日が何曜日か
を代入します。「日」は配列の添え字(0~)が日(1~)に対応
してます。

アルゴリズム的にはC言語とそんなに変わらない感じ。なでしこは
グループ昨日を使いこなしていけばそこそこ複雑なことも出きる
ので、「なでしこでアルゴリズム」みたいな本があれば面白いのに
なあ。

2013年10月6日日曜日

【なでしこ】グループをシリアライズしてみる

ああ、なんか時間取れない…と思ってるウチにかなり時間が
開いてしまった( ̄ω ̄;。

DLLの話はちょっとおいておいて、なでしこのグループの話。
なでしこのグループを作成して、それをいったんファイルに保存
しておき、今度ファイルからよんでまたグループに値を代入する
と言うお話。なでしこは中間コードを生成するわけではないので
ホントにシリアライズは出来ないんだけど、まあイベントとか
関数とか含まないグループならファイルに保存するぐらいなら
可能かな。

ってことでまずはグループを作ってみます。

------ここから------

■GRPプロジェクト
 ・{文字列}GRP名{=「GRPプロジェクト」}
 ・{整数}ノード{=0}
 ・{文字列}名前
 ・{文字列}開始日
 ・{文字列}終了日
 ・{整数}次ノード{=1}

------ここまで------

実はちょっと仕掛けが必要で、グループ要素の先頭に
文字列で「GRPプロジェクト」と、グループ名(GRP名)を
入れておきます。あとは文字列とか整数とかで値を列挙。

#あるプログラム用なので、要素名とかはあまり気に
 しないでください(^^;。

これをファイルに保存しておきたい分けですが、折角
だからXML風に保存します。

------ここから------

<GRPプロジェクト>
    <コード>0</コード>
    <名前>IIU向け新PFの開発</名前>
    <開始日>2013/10/04</開始日>
    <終了日></終了日>
    <関係者コード>100</関係者コード>
    <管理項目コード>200</管理項目コード>
    <フェーズコード>300</フェーズコード>
</GRPプロジェクト>

------ここまで------

グループ名が<GRPプロジェクト>~</GRPプロジェクト>の
タグになって、あとは要素がそれぞれのタグとなります。

これを実現するのに、下記のコードを書きました。

------ここから------

●XML化(GRPを)
 GRP名=GRPのグループ判定
 
  もしGRP名=空ならば
   #何もしない
  違えば
   メンバーズはGRPのメンバ詳細列挙
   メンバ数はメンバーズの配列要素数
   メンバ数回
    メンバーズ\(回数-1)の「(」から「)」まで範囲切り取る
   タグペアはメンバーズ\(回数-1)を「 =  」で区切る

 もし(回数-1)=0ならば
  グループ終了タグ=「</」&「{タグペア\1}」&「>」
  XML結果=「<」&「{タグペア\1}」&「>」&改行
 違えば
  アイテム開始タグ=「    」&「<」&「{タグペア\0}」&「>」
  アイテム終了タグ=「</」&「{タグペア\0}」&「>」
XML結果=XML結果&アイテム開始タグ&「{タグペア\1}」&アイテム終了タグ&改行

XML結果=XML結果&グループ終了タグ&改行&改行

  XML結果で戻る

------ここまで------

「グループ判定」「メンバ詳細列挙」というのはなでしこの命令です。
一番最初なら大くくりのタグを作って、2番目以降は1行に開始
タグと終了タグを入れてます。

ファイルから呼んでグループに戻すのは…省略(^^;。比較的簡単に
出来ますよ。最初のタグ読んだときにグループを生成し、それ以降は
生成したグループに値(<xxxx>~</xxxx>の間にある文字列)を入れる
だけ。

なでしこの変数はファジーに出来ていて、

{整数}X

と宣言したところにたとえば文字列で「1」と入れてあげても、以降
ちゃんと整数として扱ってくれます(2byte系の文字列「1」ではダメ
でした。半角数字なら 整数として代入してくれるようです)。なので
ファイルに文字列として書き出していても、次にそれを読み込んで
変数に代入すれば整数として扱ってくれるんですね~♪

2013年9月15日日曜日

【なでしこ】プラグインを作ってみる ~実装編 管理用構造体を作る~

さて、設計したプラグインをいよいよ実装するわけですが、
今回はなでしこから見ると全部「ハンドル」として見えるので、
DLL側で全てのハンドルを管理できる構造体を作成します。

------ここから------

typedef struct
{
    int index;
    unsigned long flag;
    int size;
    CRITICAL_SECTION crit;
 
    union
    {
        unsigned long byte_hdl;
        unsigned char b[4];
        void *buf_hdl;
        void *list_hdl;
        FILE *fp_hdl;
        int sock_hdl;
        HANDLE ser_hdl;
    }u;
 
    void *pextend;
 
    void *pprev;
    void *pnext;

}COMM_HANDLE;

------ここまで------

このプラグインは主に通信用途と、一般的なC的関数の実装
を意識したのでCommunication, Commonを意識して"COMM_"
としました。

構造自体は簡単で、unionの中にハンドル本体を保存する
変数、もしくはポインタが配置されてます。1,2,4byteのバイト
配列はunsigned char, unsigned short, unsigned longに相当
するものとして、これは構造体の中で値を管理します。
その他のハンドルはポインタです。あ、socketはポインタ
じゃなかったな(^^;。

pextendは各ハンドルに対して付加的な情報が必要な場合に
使用します。pprevとpnextはキューとかスタックをリスト構造で
管理してるので、それらを管理する場合にこの構造体を
連結するためのものです。

実際、なでしこの各変数もこれに近い構造体で管理している
ので、こういう言語拡張系のDLLではまずまず一般的な
形なのではないかと思います。

2013年9月9日月曜日

【なでしこ】お、イベント発生成功!

どうもプログラムが間違っていたらしく、DLLでイベント発生成功!。思ってた
通り、

------ここから------

    if (arg1->VType == varGroup)
    {
        ret = pfnako->nako_group_findMember(arg1, "発生した時");
       
        if (ret->VType != varNil)
        {
            pfnako->nako_group_exec(arg1, "発生した時");
        }
        else
        {
            /*Do Nothing*/
            ;
        }
    }

------ここまで------

の様なコード書いておいて、なでしこ側で

------ここから------

 ■テストグループ
 ・{イベント}発生した時

G1とはテストグループ
G1→発生した時は~
 「イベント発生」と表示
 
DLL引数ダンプ(G1) /*ここでDLLの関数をコール。グループを渡す*/

------ここまで------

と、やってやると、テストグループのイベントをDLL側からコールできました(^^)。
これで今までなでしこ→DLLの一方方向なコールシーケンスしか出来なかった
けど、DLL→なでしこなコールシーケンスも書ける!。ただし、一旦なでしこ定義の
関数に処理が渡ってること考えると、スレッドセーフではない気はします。
セマフォとか同期処理を上手く入れてやればDLL側のスレッドでもコールできる
かも…。

2013年9月8日日曜日

【なでしこ】イベントで行き詰る( ̄ω ̄;

なでしこのグループを作った際

------ここから------

■Gテスト
 ・{イベント}テスト動作した時

------ここまで------

みたいな感じで、イベントをかけるんですが、これを関数の引数として
DLLに渡すと、案の定PHiValueで渡ってきます。まあ、ここまでは
配列であれ整数であれ一緒なので予想通りだったんですが…

この”イベント”についてnako_group_exec()と言う関数が定義してあって
どうもグループのイベントを検索して実行できるっぽいんだけど…出来ない
( ̄□ ̄;。これが出きると、なでしこ側で定義した「関数」っぽいものを
DLL側からコールできるので、DLL側でイベントを発生させてそれに合わ
せてなでしこの動きを制御できるはずだったんだけどなあ。

もうちょっと調べてみるか。

2013年8月31日土曜日

【なでしこ】プラグインDLLの中身

なでしこのDLLに含まれる(なでしこから呼ばれる)関数はそんなに多くなく、

・ImportNakoFunction
・PluginInfo
・PluginVersion
・PluginRequire
・PluginInit
・PluginFin

の6つです。この内、自分でせっせといじる必要があるのは

・ImportNakoFunction

で、この中で自分の作成した関数(命令)を登録します。 たとえば、なでしこから
DLLに渡ってくる引数のチェックをする関数を作ったとします。

------ここから------

 void _disp_nakovar(PHiValue pvar)
{
    if (pvar != NULL)
    {
        switch (pvar->VType)
        {
            case varNil :

                DBGPRINTF("Var is Nil(%d)\n", pvar->VType);
                break;
              
            case varInt :

                DBGPRINTF("Var is Int(%d)\n", pvar->VType);
                break;

            case varStr :

                DBGPRINTF("Var is Str(%d)\n", pvar->VType);
                break;

            default :
                DBGPRINTF("Var is Unknown(%d)\n", pvar->VType);
                break;
        }
    }
}

------ここまで------

あ、デバッグ用に作ったのでDBGPRINTF()とかなってますが、
中身はprintf()です。 PHiValuはなでしこの変数を格納するための
構造体(へのポインタ)で、これに変数の種類とかいろいろ書いて
ありあす。途中省略してますが、この構造体の中身みれば、
大体のことが分かります(…って言うか、なでしこからDLLに
渡される情報はこの構造体が全てです(^^; )。

このままではなでしこに登録できませんので、なでしこの命令と
して登録できる形の関数を書く必要があります。

------ここから------

PHiValue __stdcall dnako_varchk(DWORD h)
{
    PHiValue arg1 = 0;
    PHiValue ret = 0;
    NAKO_FUNCS *pfnako = _get_nako_funcs();

    DBGPRINTF("Enter -- %s()\n", __FUNCTION__);
  
    arg1 = pfnako->nako_getFuncArg(h, 0);

    ret = pfnako->nako_var_new(NULL);

    DBGVARCHK(arg1);
  
    return(ret);
}

------ここまで------

なでしこに登録する命令は常にこの形になっています。

PHiValue __stdcall dnako_varchk(DWORD h)

は、戻り値がPHiValue、Windowsの関数コール規約__stdcall、関数名が
dnako_varchk(これはユーザーが任意に名前つけられます)、引数は
DWORD型のh一つだけとなります。

命令の引数から実際の変数を取得する場合は

・pfnako->nako_getFuncArg(h, 0)

を使用します。pfnakoは関数セットを構造体として持っていて、
そこへのポインタです。この関数を実行することで、引数のh
から、PHiValueの変数を引っ張ってこれる仕組みです。

命令の引数が複数ある場合は、

arg1 = pfnako->nako_getFuncArg(h, 0);
arg2 = pfnako->nako_getFuncArg(h, 1);
arg3 = pfnako->nako_getFuncArg(h, 2);

と、引数分実行すれば順番に取得できます。つまりnako_getFuncArg()
の第二引数は、変数のリストだか配列だかのインデックスってこと
ですね。先頭のインデックスは0です。

こうやって取得したarg1はPHiValue型ですので、必要に応じてここから
整数や文字列を取り出します。pfnakoの中に、

・nako_var2int() /*PHiValueからint型の値取り出し*/
・nako_var2str() /*PHiValueから文字列取り出し*/

などがあるので、必要に応じて使用します。

最後に、この関数はデバッグ用だったので、戻り値は特に必要なかった
ですが、実際に必要な場合には、

・ret = pfnako->nako_var_new(NULL);

でPHiValue型の空の変数を作成した後、


・nako_int2var()

などを使用して、PHiValue型に実際をセットし、これをなでしこに返します。
すると、それがなでしこ命令を実行した際の戻り値になるわけですね~♪

最後はこのdnako_varchk()をなでしこに登録します。上でも書きましたが
登録するのは、

ImportNakoFunction()の中身でやります。

------ここから------

NAKO_API(void) ImportNakoFunction(void)
{
    NAKO_FUNCS *pfnako = _get_nako_funcs();
   
    DBGPRINTF("Enter -- ImportNakoFunction()\n");
   
    pfnako->nako_addFunction("DLL引数ダンプ", "A", dnako_varchk, 0);
}

------ここまで------

・pfnako->nako_addFunction("DLL引数ダンプ", "A", dnako_varchk, 0);

が実際に登録してる場所で、"DLL引数ダンプ"はなでしこの命令名、
"A"がその時の引数、 "dnako_varchk"が上で作ったCの関数名です。
最後の0は…分かりませんヾ(;´▽`A``。サンプルに0が設定されてたので
0にしてあります…。

なでしこ命令の引数ですが、"A"と書いた部分に"A,B"と書いておけば
引数が2つってことになります。またここに"Aの"とか書いておけば、
なでしこ命令としても「AのDLL引数ダンプ」みたいに書けます。上の
場合は

・DLL引数ダンプ(A)

と、ちょっとC言語っぽくなりますが、今回は引数が多めの命令も
ありますので、これで統一します。

2013年8月24日土曜日

【なでしこ】プラグインを作ってみる ~設計編 その10~

最後はハンドル自体に対する関数です。

------ここから------

・ハンドルタイプ取得
    書式:ハンドルタイプ([int]ハンドル)
    戻値:[int]ハンドルタイプ
    説明:指定ハンドルの種別を取得する。戻り値は以下のとおり。
      
       -1 :エラー(使われてない、など)
        1 :バイト
        2 :バッファ(リングバッファ)
        4 :ファイル
        8 :キュー
       16 :スタック
       32 :ソケット
       64 :シリアルポート
      
・ハンドル解放
    書式:ハンドル解放([int]ハンドル)
    戻値:なし
    説明:取得したハンドルを解放する。対象がメモリの場合はメモリ
       が解放され、バイナリ(ファイル)やソケットの場合は
          それらがクローズされる。

------ここまで------

キューとかスタックにハンドルをつないだ場合、取得した際のタイプが
分からないのでそれを取得できる関数を用意します。

各関数群で「ハンドルを確保」した場合は、それを使わなくなった時点で
「ハンドル解放」します。ガーベージコレクトの様な高度な処理は内部で
持ってませんのでヾ(;´▽`A``。

尚、解放時、ハンドルのタイプによって実施する処理は違ってるんですが
それはこの関数内部で判断して実施してるので、とにかくいらなくなったら
解放してください(^^;。

【なでしこ】プラグインを作ってみる ~設計編 その9~

シリアル通信用の関数群です。組み込み系の仕事してると、
ボードとの通信は大体シリアルなので、日常的にシリアル
通信を使います。なでしこにはRS232Cのプラグインも入って
ますが、以前使ったら文字列しか送受信できないみたいだったので
再定義します。

------ここから------

 ・シリアルオープン
    書式:シリアルオープン([int]ポート、[int]ボーレート)
    戻値:[int]ハンドル
    説明:ポートとボーレートを指定して、シリアルポートをオープン
        する。ポート、ボーレート以外のパラメータは、
        
           データ  :8bit
            パリティ :なし
            ストップ :1bit
            フロー制御:なし
         
          となる。
        
          成功した場合は0以上のハンドル値が返される。失敗した場合は
          -1が返される。

・シリアル送信
    書式:シリアル送信([int]ハンドル、[int]バッファ、[int]サイズ)
    戻値:[int]サイズ
    説明:シリアルオープンで取得済のハンドル、及びバッファ確保した
         ハンドルを指定してサイズ分のデータを送信する。
        
          成功した場合には送信出来たサイズが、失敗した場合には-1が
          返される。

・シリアル受信
    書式:シリアル受信([int]ハンドル、[int]バッファ、[int]サイズ)
    戻値:[int]サイズ
    説明:シリアルオープンで取得済のハンドル、及びバッファ確保した
         ハンドルを指定してサイズ分のデータを受信する。

          成功した場合には受信サイズが、失敗した場合には-1が
          返される。

・シリアルデータサイズ
    書式:シリアルデータサイズ([int]ハンドル)
    戻値:[int]サイズ
    説明:シリアルオープンで取得済のハンドルで指定されるシリアル
       ポートに対して、そのバッファに受信されているデータ
          サイズを取得する。
        
          ここでのバッファとは上記バッファ確保したものではなく
          Windowsのシリアルドライバが保持している受信バッファで
          ある。

------ここまで------

ネットワーク通信同様、受信にはスレッド&リングバッファを使いたい
ところですが、こちらも受信関数だけです。リングバッファだけは作って
みたものの…。Windowsの場合はWindowsのデバドラ自体がバッファ
持ってるので、スレッドがなくても処理は可能です。

【なでしこ】プラグインを作ってみる ~設計編 その8~

なでしこでもプラグインのnakonet.dllを使うとネットワーク通信
できますが、もうちょっとソケットを意識した関数を作ります。

------ここから------

 ・ソケットオープン
    書式:ソケットオープン([int]タイプ)
    戻値:[int]ハンドル
    説明:タイプを指定してソケットを作成(オープンする)。
       タイプには以下の何れかを指定する。
           
            0 : TCP
            1 : UDP
        
          成功した場合には0以上のハンドル値が返される。失敗
          した場合には-1が返される。

 ・ソケット接続待ち
    書式:ソケット接続待ち([int]ハンドル、[int]ポート)
    戻値:[int]結果
    説明:ソケットオープンで取得済のハンドルと、指定のポートを
          使って、TCPで相手が接続してくるのを待つ。
        
          成功した場合は0が、失敗した場合は-1が返される。成功
          した場合、後述の「相手IPアドレス取得」命令を使用
          して、接続相手のアドレスを取得することが出来る。

・ソケット接続
    書式:ソケット接続([int]ハンドル、[str]相手のアドレス、[int]ポート)
    戻値:[int]結果
    説明:ソケットオープンで取得済のハンドルと、サーバ側のアドレス、
         ポートを指定してTCPで接続する。
        
          接続が成功した場合には0が、失敗した場合には-1が返される。

・TCP送信
    書式:TCP送信([int]ハンドル、[int]バッファ、[int]サイズ)
    戻値:[int]サイズ
    説明:ソケットオープンで取得済のハンドル、且つこのソケットで
       相手に接続している場合に、バッファで指定されるハンドル
          のデータをサイズ分送信する。バッファはバッファ確保で
          取得したハンドルを指定すること。
        
          成功した場合には送信出来たサイズが返される。失敗した
          場合には-1が返される。

・TCP受信
    書式:TCP受信([int]ハンドル、[int]バッファ)
    戻値:[int]サイズ
    説明:ソケットオープンで取得済のハンドル、且つこのソケットで
       相手に接続している場合に、バッファで指定されるハンドル
          にデータを受信する。

          成功した場合には受信出来たサイズが返される。失敗した
          場合には-1が返される。

・UDP送信
    書式:UDP送信([int]ハンドル、[int]バッファ、[str]相手アドレス、[str]ポート)
    戻値:[int]サイズ
    説明:ソケットオープンで取得済のハンドルと、送信対象のバッファ
       のハンドル、及び相手アドレスとポートを指定してデータを
          送信する。ソケットハンドルはUDPでオープンされていること。
        
          成功した場合には送信サイズが返さえる。失敗した場合には
          -1が返される。

・UDP受信
    書式:UDP送信([int]ハンドル、[int]バッファ、[str]ポート)
    戻値:[int]サイズ
    説明:ソケットオープンで取得済のハンドルと、受信データ書きこみ
       用のバッファハンドル、及びポートを指定してデータを受信
          する。なお、ポートが設定されるのは最初の1回だけど、それ
          以降は無視される。
        
          成功した場合には受信出来たサイズが返される。失敗した
          場合には-1が返される。

・相手IPアドレス取得
    書式:相手IPアドレス取得(#引数なし)
    戻値:[str]相手IPアドレス(文字列)
    説明:TCP通信で接続した相手のアドレス、及びUDP通信で受信した
       場合の相手のIPアドレスを文字列で返す。DLL内部では
          1箇所でしか記憶していないので、複数ソケットを開いている
          場合等は、最後に接続/受信させれたものが記憶される。

------ここまで------

普通ネットワーク系のプログラムは受信用にスレッド使うのが
一般的ですが、今回は関数だけ用意してスレッドには対応して
ません。なのでちょっと使いにくいかも…。UDPでちょっと送受信
するぐらいなら使えますかね。

【なでしこ】プラグインを作ってみる ~設計編 その7~

バイト処理の関数に近いものがありますが、ビット処理の関数群です。
なでしこだけでなく、Luaとかもビット操作が弱い傾向にあるので、
こういう関数は意外に役にたつかも(Luaは5.2系でビット処理の関数が
入った様ですが)。

------ここから------

・ビットチェック
    書式:ビットチェック([int]ハンドル、[int]パターン)
    戻値:[int]結果
    説明:対象となるハンドルと、パターンを指定して、パターンビット
       が対象に含まれているかチェックする。対象はバイト確保
          されたハンドルであること。
         
          パターンが含まれている場合には1(TRUE)が、含まれていない
          場合は0(FALSE)が返される。引数が不正な場合には0が返される。

・ビットセット
    書式:ビットセット([int]ハンドル、[int]パターン)
    戻値:[int]結果
    説明:対象のハンドル値に、パターンビットを設定する。対象は
         バイト確保されたハンドルを指定する。
         
          成功した場合には0が、引数に不正があった場合には-1が
          返される。

・ビットクリア
    書式:ビットクリア([int]ハンドル、[int]パターン)
    戻値:[int]結果
    説明:対象のハンドル値の、パターンで指定されるビットをクリア
       する。対象はバイト確保されたハンドルであること。
         
          成功した場合には0が、引数に不正があった場合には-1が
          返される。

------ここまで------

普通にプログラミングしてるとあまり使わないんですが、組み込み
系のプログラムでレジスタいじったり、あと通信パケットの内容を
操作したりする場合は意外とビット操作が使われてます。これと
バイト操作系のところで定義した左右シフトの関数があれば、
大体のことは出来ますかね~ヾ(´ー` )ノ

【なでしこ】プラグインを作ってみる ~設計編 その6~

今回の設計はファイルです。バイナリ形式でファイルを扱いますが、
「バイナリファイル~」と書くと長いので、「バイナリ~」とします。

------ここから------

・バイナリオープン
    書式:バイナリオープン([str]ファイル名、[int]モード)
    戻値:[int]ハンドル
    説明:ファイル名で指定されたファイルを、モードで指定された方法で
       オープンする。モードには0,1,2,3の何れかを指定し、意味は
          以下のとおり。

           0 : 読込専用
           1 : 書込専用
           2 : 読み書き
           3 : 追記
           
         ファイルは常にバイナリとしてオープンされる。テキストモード
          で扱いたい場合には、なでしこの組み込み命令を使用すると良い。

         成功すると0以上のハンドルが返される。失敗した場合には-1が
          返される(ファイルがない、モードが範囲外など)

・バイナリ読込
    書式:バイナリ読込([int]ハンドル、[int]先ハンドル、[int]サイズ)
    戻値:[int]サイズ
    説明:バイナリオープンされているハンドルから、サイズ分を読み
         込んで先ハンドル(バッファ)に書き込む。読み込めるサイズは
          コピー先のバッファサイズに依存し、バッファサイズ以上の
          データは読み込まない。読み込めたサイズは戻り値として
          返される。
         
          読み込み開始位置は現在の開始位置で、読み込む毎にオフセット
          がプラスされる。現在の開始位置はバイナリ位置取得命令で
          取得出来、位置の変更はバイナリシーク命令で可能である。
         
          引数が不正な場合等、エラーの場合は-1が返される。

・バイナリ書込
    書式:バイナリ書込([int]ハンドル、[int]元ハンドル、[int]サイズ)
    戻値:[int]サイズ
    説明:作成済みのバッファ(元ハンドル)からサイズ分読み込んで、
     バイナリオープンされているハンドルに対して書き込む。
          書き込めるサイズは元ハンドルのサイズに依存し、それ以上の
          サイズを指定した場合は、書き込めるだけ書き込む。
          (データがある分だけ書き込む)。書き込めたサイズが戻り値
          として返される。
         
          書込開始位置は、書込専用、読み書き用にオープンしている場合は
          ファイルの先頭から開始し、書き込む毎にオフセットがプラスされ
          る。既存ファイルの場合は一旦ファイルが消去されるので注意する
          こと。追記モードの場合はファイルの終端から書込が開始される。
         
          引数が不正な場合等、エラーの場合は-1が返される。

・バイナリシーク
    書式:バイナリシーク([int]ハンドル、[int]オフセット)
    戻値:[int]オフセット
    説明:バイナリオープンされているハンドルの読み込み・書込開始
       位置をオフセットの値に設定する。オフセットは0以上の
          値で、ファイルサイズ以上の値を設定した場合には、ファイルの
          末尾となる。
         
          成功した場合にはオフセット値が、失敗した場合には-1が
          返される。

・バイナリ位置取得
    書式:バイナリ位置取得([int]ハンドル)
    戻値:[int]位置
    説明:バイナリオープンされているハンドルの、現在開始位置を
       返す。引数が不正だった場合には-1が返される。

------ここまで------

ANSIでいう所のfopen, fread, fwrite, fseek, ftellに相当する関数です。
バイナリじゃない形式でファイルを扱いたい場合は、なでしこの「開く」
とか使ってください。

あと、今気がつきましたが、なでしこには「バイナリ取得」とか「バイナリ設定」
と言う命令がありますね( ̄□ ̄;。混同しない様に気をつけて下さい。

2013年8月18日日曜日

【なでしこ】プラグインを作ってみる ~設計編 その5~

キューとスタックは一緒に。実際実装は殆ど一緒で、FIFOに
なるかFILOになるかの差です。

------ここから------

・キュー作成
    書式:キュー作成(#引数なし)
    戻値:[int]ハンドル
    説明:空のキューを作成して、そのハンドルを返す。キューに対しては
       本ライブラリで生成出来るハンドルを追加・取得出来る(FIFO)。
         
          成功した場合にはハンドル値が、失敗した場合には-1が返される。

・キュー追加
    書式:キュー追加([int]キュー、[int]ハンドル)
    戻値:[int]結果
    説明:指定のキューハンドルに、ハンドルを追加する。
   
       成功した場合は0が、失敗した場合は-1が返される。

・キュー取得
    書式:キュー取得([int]キュー)
    戻値:[int]ハンドル
    説明:指定されたキューから、先頭の1要素を取得して返す。
   
       成功した場合にはハンドル値が、失敗した場合には-1が返される。

・キュー要素数取得
    書式:キュー要素数([int]ハンドル)
    戻値:[int]要素数
    説明:指定されたキューに繋がれているハンドル数(要素数)を
       返す。失敗した場合には-1が返される。

・スタック作成
    書式:スタック作成(#引数なし)
    戻値:[int]ハンドル
    説明:空のスタックを作成して、そのハンドルを返す。スタックに対しては
       本ライブラリで生成出来るハンドルを追加・取得出来る(LIFO)。
         
          成功した場合にはハンドル値が、失敗した場合には-1が返される。

・スタック追加
    書式:スタック追加([int]スタック、[int]ハンドル)
    戻値:[int]結果
    説明:指定のスタックハンドルに、ハンドルを追加する。
   
       成功した場合は0が、失敗した場合は-1が返される。

・スタック取得
    書式:スタック取得([int]スタック)
    戻値:[int]ハンドル
    説明:指定されたスタックから、末尾の1要素を取得して返す。
   
       成功した場合にはハンドル値が、失敗した場合には-1が返される。

・スタック要素数取得
    書式:スタック要素数([int]ハンドル)
    戻値:[int]要素数
    説明:指定されたスタックに繋がれているハンドル数(要素数)を
       返す。失敗した場合には-1が返される。

------ここまで------

キュー、スタックを確保すると、管理用のヘッダが内部で生成されて
それにハンドルを追加していきます。追加できるハンドルは特に
種別を規定はしませんが…まあ普通はバイトハンドルかバッファ
ハンドルですね。

…と、今書いてて思い出しましたが…キューかスタックに繋がってる
ハンドルは今のところ無条件に開放できてしまうな( ̄□ ̄;。
なんとかせねば…

2013年8月17日土曜日

【なでしこ】プラグインを作ってみる ~設計編 その4~

もう1種類のバッファとして、リングバッファを準備します。シリアルのデータ
受信をスレッドにする場合にはリングバッファを仕様することが多いので、
前もって準備しておきます。

※なでしこではスレッドには対応してませんので、対応する場合は
 DLL内でスレッドを生成することになります。…今のところ対応予定は
 ないですが(^^;。

------ここから------

 ・リングバッファ確保
    書式:バッファ確保([int]サイズ)
    戻値:[int]ハンドル
    説明:メモリを動的に確保して、そのハンドルを返す。成功した場合、
       0以上のハンドル値が、失敗した場合には-1が返される。
        
          なお、メモリは動的に確保されているので、使用後はかならず
          ハンドルの解放を実施して確保されたメモリ領域を解放する
          こと。
        
          「バッファ確保」と処理内容は一緒だが、以降このバッファは
          リングバッファとして扱われる。

・リングバッファ読込
    書式:リングバッファ読込([int]ハンドル、[int]先ハンドル、[int]サイズ)
    戻値:[int]サイズ
    説明:確保されているリングバッファハンドルから、サイズ分を読み
         込んで先ハンドル(バッファ)に書き込む。読み込めるサイズは
          コピー先のバッファサイズに依存し、バッファサイズ以上の
          データは読み込まない。読み込めたサイズは戻り値として返される。
        
          リングバッファなので、読み込みの開始位置は現在の読込位置
          となり、読み込んだサイズ分は以降書込可能領域となる。
        
          引数が不正な場合等、エラーの場合は-1が返される。

・リングバッファ書込
    書式:リングバッファ書込([int]ハンドル、[int]元ハンドル、[int]サイズ)
    戻値:[int]サイズ
    説明:作成済みの元ハンドル(バッファ)からサイズ分読み込んで、
       確保されているリングバッファハンドルに対して書き込む。
          書き込めるサイズは元ハンドルのサイズに依存し、それ以上の
          サイズを指定した場合は、書き込めるだけ書き込む。
          (データがある分だけ書き込む)。書き込めたサイズが戻り値
          として返される。
        
          書き込み位置はリングバッファ中の書き込み可能な領域の先頭
          からとなり、書き込んだ分は以降読込可能となる。書き込む前に
          空き領域を知りたい場合には「リングバッファ空きサイズ」
          命令でサイズを取得出来る。
        
          引数が不正な場合等、エラーの場合は-1が返される。

・リングバッファ読込サイズ
    書式:リングバッファ読込サイズ([int]ハンドル)
    戻値:[int]読込可能サイズ
    説明:確保されているリングバッファハンドルの、現在読み込める
       データサイズを返す。
        
          引数が不正な場合等、エラーの場合は-1が返される。

------ここまで------

リングバッファは一つのバッファを、読み込み側と書き込み側で
共有するためのものです。まず書き込みを行って、その部分が
読み込まれれば、そこは再度書き込み可能となります。

バッファの先頭から書き始めて終端まで行ったらまた先頭に戻り、
そこが「書き込み可能」になっていればさらに書き込みます、リング
の様にグルグルとバッファを繰り返し使うのでリングバッファです。

【なでしこ】プラグインを作ってみる ~設計編 その3~

次に、メモリ(バッファ)制御系の関数の仕様を決めます。

------ここから------

 ・バッファ確保
    書式:バッファ確保([int]サイズ)
    戻値:[int]ハンドル
    説明:メモリを動的に確保して、そのハンドルを返す。成功した場合、
       0以上のハンドル値が、失敗した場合には-1が返される。
        
          なお、メモリは動的に確保されているので、使用後はかならず
          ハンドルの解放を実施して確保されたメモリ領域を解放する
          こと。

・バッファクリア
    書式:バッファクリア([int]ハンドル、[int]クリア値)
    戻値:[int]結果
    説明:バッファ確保命令で取得したハンドルの領域をクリア値を用いて
       クリアする。クリア値には0~255(0xFF)までの1byte値を指定
          する。
        
          成功した場合は0が、無効なハンドル、クリア値を指定した
          場合は-1が返される。

・バッファコピー
    書式:バッファコピー([int]元ハンドル、[int]先ハンドル、[int]サイズ)
    戻値:[int]結果
    説明:既に確保されているコピー元ハンドルから、コピー先ハンドルに
       データをコピーする。先ハンドルはバッファでなくては
          ならないが、元ハンドルについてはバッファ、もしくは
          上記バイト確保命令で取得したハンドルでも良い。
        
          成功した場合は0が、無効なハンドルを指定した場合には-1が
          返される。

・バッファ読込
    書式:バッファ読込([int]ハンドル、[int]オフセット)
    戻値:[int]読込データ
    説明:既に確保されているメモリ領域(ハンドル)の、所定のオフセット
       位置から、1byteのデータを取得して返す。
        
          無効な引数を指定した場合には0が返される。

・バッファ書込
    書式:バッファ書込([int]ハンドル、[int]オフセット、[int]データ)
    戻値:[int]結果
    説明:既に確保されているメモリ領域(ハンドル)の、所定のオフセット
       位置に、1byteのデータを書き込む。データには0~255の値を
          指定する。
        
          成功した場合には0が、無効な引数を指定した場合には-1が
          返される。

・バッファ比較
    書式:バッファ比較([int]ハンドル、[int]ハンドル、[int]サイズ)
    戻値:[int]結果
    説明:既に確保されている2つのバッファハンドルのサイズ分のデータ
       を比較する。
        
          比較した結果内容が同じであれば1、違っていれば0、エラーが
          あった場合には-1を返す。

------ここまで------

一般的にCで実施するmalloc, memcpy, memset, memcmpなどが使える
様にするために上記の関数を準備します。読み書きは1byteずつに
しましたが、複数にした方がいいのかなあ…。バッファコピーもオフセット
はつけませんでしたが、任意の位置に任意のサイズコピーできるほうが
いい気がしてきたので、その内仕様を変更しようかと思います。

freeに相当する関数がここには含まれてませんが、ハンドルを開放する
ための関数を後ほど準備します。

※最終的なものは修正後、まとめて公開します。

2013年8月15日木曜日

【なでしこ】プラグインを作ってみる ~設計編 その2~

では、バイト制御系の関数仕様を決めていこうと思います。

------ここから------

・バイト確保
    書式:バイト確保([int]バイト数、[int]初期値)
    戻値:[int]ハンドル
    説明:バイト数に1,2,4の何れかを指定して、変数を確保し、初期値を
       代入する。以降、戻り値のハンドルを使用して、値を読み書き
          出来る。
         
          確保されるメモリ領域は内部でunsignedで扱われる。この値は
          なでしこ側から見るとグローバルな領域になるので、関数内等
          ローカルスコープから本関数をコールした場合も、変数自体は
          グローバルに確保されていることに注意すること(つまり、
          なでしこの関数を抜けても、変数領域は解放されない)。
         
          確保が成功した場合には0以上の整数が、失敗した場合には-1
          が返される。使用が終了した場合はハンドルを解放すること。

・バイト読込
    書式:バイト読込([int]ハンドル)
    戻値:[int]変数値
    説明:バイト確保命令で取得したハンドルの、現在の値を取得する。
       戻り値は整数型になる。無効なハンドル値を指定した場合には
          常に0が返される。
         
・バイト書込
    書式:バイト書込([int]ハンドル、[int]値)
    戻値:[int]結果
    説明:バイト確保命令で取得したハンドルに対して、指定した値を
       書き込む。書き込める値の範囲は確保されている領域サイズに
          より異なり、範囲外の値を指定した場合にはエラーとなる。
         
          書込が成功した場合には0が、失敗した場合には-1が返される。

・バイト右シフト
    書式:バイト書込([int]ハンドル、[int]シフト量)
    戻値:[int]結果
    説明:ハンドルで確保されているバイトに対して、シフト量で指定
       した分、右シフトを実施する。シフト量は確保されている
          バイトのサイズにより、1byteの場合は7、2byteの場合は15、
          4byteの場合は31となる。
         
          成功した場合、シフト後の値が元の値に上書きされ、0が
          返される。失敗した場合には-1が返される。

・バイト左シフト
    書式:バイト書込([int]ハンドル、[int]シフト量)
    戻値:[int]結果
    説明:ハンドルで確保されているバイトに対して、シフト量で指定
       した分、左シフトを実施する。シフト量は確保されている
          バイトのサイズにより、1byteの場合は7、2byteの場合は15、
          4byteの場合は31となる。
         
          成功した場合、シフト後の値が元の値に上書きされ、0が
          返される。失敗した場合には-1が返される。

・エンディアン変換
    書式:エンディアン変換([int]ハンドル)
    戻値:[int]結果
    説明:バイト確保命令で取得したハンドルに対応する値のエンディアン
       変換を実施する。変換後の値はハンドル対応値に上書きされる。
         
          成功した場合は0が、無効なハンドルを指定した場合は-1が
          返される。

------ここまで------

なでしこでは、その他現代風の高級言語(スクリプト、ですかね)
に似て、変数の型を指定しなくても関数の結果を受けられますが、
「整数」「数値」など指定することも可能です。

「整数」と言うとCで言うところのintで宣言されて、サイズ的には4byte
の空間(メモリ)が確保されている様です。

バイナリデータを扱う場合は、サイズとして1,2,4byteのデータを
意識的に確保して使用することが多いので、バッファと一部被る
部分はありますが「バイト確保」関数を準備しました。

バイト制御系の関数に限らず、このDLLでは「~確保」関数を
用いてDLL内で必要なメモリ等を確保してます。メモリや構造体を
そのままなでしこに渡すことは出来ないので、なでしこに対して
渡すのは「ハンドル」値です。これはなでしこで言うところの「整数」
です。以降、このDLLのその他の関数を使用して操作を行う
場合は、引数にこの「ハンドル」を指定します。

2013年8月12日月曜日

【なでしこ】プラグインを作ってみる ~設計編 その1~

では、自分用のプラグインを作ってみましょう!。前にも書きましたが、
なでしこはメモリ操作系の関数が殆どないので、なんとなくC言語っぽく
使える様に、次の様な関数を含むDLLを作ってみたいと思います。

■バイト制御
・バイト確保
・バイト読込
・バイト書込
・バイト右シフト
・バイト左シフト
・エンディアン変換

■メモリ(バッファ)制御
・バッファ確保
・バッファクリア
・バッファコピー
・バッファ読込
・バッファ書込
・バッファ比較

■メモリ(リングバッファ)制御
・リングバッファ確保
・リングバッファ読込
・リングバッファ書込
・リングバッファ読込サイズ

■リスト(キュー)制御
・キュー作成
・キュー追加
・キュー取得
・キュー要素数取得

■リスト(スタック)制御
・スタック作成
・スタック追加
・スタック取得
・スタック要素数取得

■ファイル(バイナリファイル)制御
・バイナリオープン
・バイナリ読込
・バイナリ書込
・バイナリシーク
・バイナリ位置取得

■ビット制御
・ビットチェック
・ビットセット
・ビットクリア

■ソケット制御
・ソケットオープン
・ソケット接続待ち
・ソケット接続
・TCP送信
・TCP受信
・UDP送信
・UDP受信

■シリアル制御
・シリアルオープン
・シリアル送信
・シリアル受信

■ハンドル制御
・ハンドル解放
・ハンドルタイプ取得

あれもこれも…と思ってたらちょっと欲張りすぎたかな(^^;。実際に
実装したときちょっと後悔したけど、まま大半は定型作業だから
ヨシとしよう。

次は関数の仕様をざっくり決めますよ!。それはまた次回。

2013年8月9日金曜日

【なでしこ】プラグインをMS VC++ Express(2010)で作成する

仕事が休みの日にしか書かないので非常に気まぐれな更新ですが、
ボチボチやっていきましょうか!。

さて、なでしこのプラグインを作ろうと思っても、実際あまり情報がない
訳ですよ。Google先生に聞いてみると、Google Codeのなでしこリポジトリ
に、ソースコード一式がありましたが、どうやらこれはVC++用ではない
様子。でも、これを元にして作れそうですよ。

ってことで、まずMSのサイトからVC++ Express 2010をダウンロード
してきます →こちら

2012もリリースされてますが、必要なのはVC++だけなので、2010を
使用します。で、VC++用のプロジェクトを作成したので一式を
公開します →こちら

上記のリンクを辿るとbase.7zを取得できます。これを解凍すると、 
以下の様なファイルとディレクトリが作成されます。

\base
|   debug.c
|   dnako_import.c
|   dnako_import.h
|   dnako_import_def.h
|   dnako_import_types.c
|   dnako_import_types.h
|   dnako_plugin_body.c
|   ReadMe.txt
|  
\---nako_dll_base
        dnako_import.def
        nako_dll_base.sln
        nako_dll_base.vcxproj

VC++が入っていれば\nako_dll_base\nako_dll_base.slnを実行
すると、VC++が起動しますので、このままコンパイルすれば
サンプルDLLが出切るハズ(何も設定しない状態では\nako_dll_base\Debug
の下にDLLが出来ます)。これをなでしこのプラグインフォルダに
コピーすれば使用できます。名前を変えたい場合は、VC++の
プロジェクトオプションを変更してください。

尚ソースコードは、上記なでしこのGoogle Codeサイトから
取得したものを若干変更してありますのであしからず。
(主にエラー処理とか、関数内で"#include呼んでファイル展開
してたのを修正とか、その程度です)。

これでだれでもDLLが作れる様になりますね!ヽ( ̄▽ ̄)ノ。
でももうちょっと複雑な関数を実装したサンプルがあっても良さ
そうなので、実際にこれをベースにして何か作ってみようかと
思います。それはまた次回♪

2013年8月4日日曜日

【なでしこ】できること、できないこと

なでしこの命令一覧 を見てると分かりますが、日常の定型作業などを
行うには使い易い言語です。ちょこちょっと書いて動かすのがいい感じ
ですかね~(^^)。

扱えるデータの種類としては、大体のモノは扱えますが、メインターゲットは
「文字列」な感じです。ファイルにしてもテキストファイルは非常に扱い易い。
ただ、組み込みとか通信系のプログラマな自分にからすると、バイナリ系が
非常に扱いにくい( ̄へ ̄;。

以前に一度RS232C(シリアル通信)を使うプログラムを組もうとして、バイナリ
データが扱えなくて諦めた経緯があります。またTCP/IPとかはソケットで
扱えると便利なんだけど…そのAPIも今のところありません。

ファイル用のAPIも揃ってはいますが、Cをメインで使ってる自分としては
ANSIっぽいAPIが欲しいな~と思うわけです。

データは配列など一通り揃ってますが、メモリとして扱うにはちょっと
難しいかな…と言うことで、なかなかC言語な頭では使いにくい部分も
あり、こりゃ一筋縄で行かないなあ( ̄ω ̄;。

しかし!、なでしこには「プラグイン」と言う優れた仕組みが備わっていて
自分でプラグイン作ればAPIを追加できますよ!。と、いう事でサクッと
プラグインを作ってみたいと思います。

【なでしこ】プログラミング言語「なでしこ」

「なでしこ」と言うプログラミング言語があります。この言語は日本語でプログラミング
できます!。素晴らしい(^^)。個人的にはCなどでもプログラムできますが、面白そう
なので「なでしこ」やってみようかな~。

で、まずは「なでしこ」の本体を取得します。→こちら

なでしこはインタプリタ型の言語なので、あまり高速な処理速度は望めませんが、
VC++とか使うこと考えたらお手軽♪。GUIの簡易RADもついてますし、なかなか
楽しめそうです(正直、この簡易RADがついてるのが一番の魅力(ё∇ё) )。

あと、参考書としてはAmazonでも何冊か出てますが、上記のホームページや
こちら で入手可能なPDFを読めば、大体の扱い方は分かると思います。まずは
いじって楽しむのが一番ですかね~。