PIPE 1本双方向+EVENT:Lua から Python でグラフ出力

2017-02-10 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-02-08)の記事「Lua/Lua:PIPE 1本で双方向+EVENT」迄で、
クライアント(メイン)側は GSL Shell だが、
サーバ(スレーブ)側は GSL Shell でもPython でも行ける様になった。

しかし、これまではテキストデータの1回毎の送受信だった。

その後の学習で、
複数行一括送受信バイナリデータ送受信も行けた。

そうすると、
GSL Shell から Python の matplotlib.pyplot を利用することを考えた。

以前(2016-07-25)の記事「LuaPy:matplotlib.pyplot 実例
の様なコト。


学習の結果、・・・・・

サーバ側 「Slave_Plot.py」は:(少しは汎用的?なコード)
# coding: utf-8
# ---------------------------------- Slave_Plot.py
import win32pipe, win32file
import win32event
import time
print( 'Start Slave' ) # ---------- デバッグ用

#----- マスタ(クライアント)から呼ばれ:
# イベントハンドルを非シグナルで作成。
E1 = win32event.CreateEvent( None, 1, 0, 'EVENT1' )
# シグナル状態にする。
win32event.SetEvent( E1 )

#-- PIPE オープン
P1 = win32file.CreateFile("\\\\.\\pipe\\PIPE1",
win32file.GENERIC_READ | win32file.GENERIC_WRITE,
0, None, win32file.OPEN_EXISTING, 0, None)

# ------------------------------------ 処理:
# -- シグナル状態チェック -- off 迄
flg = win32event.WaitForSingleObject( E1, 0 )
while flg == 0: # ----- シグナル状態==0、非~==258(初期状態)
flg = win32event.WaitForSingleObject( E1, 0 )

# -- リクエスト受信 3回
_, data1 = win32file.ReadFile( P1, 4096 )
exec(data1) ################################ これ init

_, data2 = win32file.ReadFile( P1, 4096 ) ##### バイナリデータ想定

_, data3 = win32file.ReadFile( P1, 4096 )
exec(data3) ################################ これがメイン

time.sleep( 1 ) # 秒数 ----- ダミー

dat = "END"
# -- シグナル on にして、結果送信
win32event.SetEvent( E1 )
win32file.WriteFile( P1, dat )

print( 'End Slave' ) # ---------- デバッグ用
_=raw_input() # -- [Enter]キー入力待ち。
の様なコード。

これを使ったマスター側は、・・・
------------- Master_Pyplot.gsl
require'cdef_PIPE_Event_SUB'
--[[ ffi.cdef 以外に、以下も定義:
charA = |s| ffi.cast( 'char*', s )
C = ffi.C; band = bit.band
Buf = ffi.new('uint8_t[4097]')
nIO = ffi.new('uint32_t[1]')
]]
print( 'Start' ) -- デバッグ用
-- パイプを作成
P1 = C.CreateNamedPipeA( charA("\\\\.\\pipe\\PIPE1"), 3, 0, 1, 0, 0, 100, 0 )
-- サーバー立ち上げ
os.execute('start Slave_Plot.py') -- <<<====================
-- PIPE オープン待ち
rtn=C.ConnectNamedPipe( P1, 0 )

-- イベントオブジェクト取得
E1 = C.OpenEventA( 0x001F0003, 0, charA('EVENT1') )
-- ^^^^^^^^^^ EVENT_ALL_ACCESS
-- 立ち上げ確認:シグナル状態チェック for Start
repeat until band( C.WaitForSingleObject( E1, 1 ), 2 ) == 0 -- on 迄
----- シグナル off に ( 初期化 )
C.ResetEvent( E1 )

------------------------------------ 主処理:
str1=[[
import ctypes as ct
def VoidA(x):
return ct.cast( x, ct.c_void_p )
def np_data( x ):
return ct.cast( id(x), ct.POINTER(ct.c_long) ) [2]
]]
IBuf=ffi.cast('int32_t*',Buf)
xy={ 1, 2, 3, 4, 1, 4, 2, 5 }
for n=0,7 do IBuf[n]=xy[n+1] end
str3=[[
xx=4
import numpy as np # これは必須(?)
import matplotlib.pyplot as plt # これはメイン。
x = np.zeros( xx, dtype=np.int )
y = np.zeros( xx, dtype=np.int )
_=ct.cdll.msvcrt.memcpy( np_data(x), data2, xx*4 )
_=ct.cdll.msvcrt.memcpy( np_data(y), VoidA(data2).value + 4*xx, xx*4 )
plt.figure( figsize=(8, 6) ) # 図のサイズ
plt.title( 'Title', fontsize=18, fontname='serif' ) # 図のタイトル
plt.plot( x, y, ls='--', lw=2, c='#FF8020' ) # 線種、太さ、色
plt.xlabel( 'X-Axis', fontsize=12, fontname='serif') # X軸のラベル
plt.ylabel( 'Y-Axis' )
plt.legend( ( 'legend', ) ) # 凡例 ( 1要素のタプルではカンマが必要 )
plt.show() # 画面表示
]]

-- シグナル off にして、リクエスト送信3回
C.ResetEvent( E1 )
_ = C.WriteFile( P1, charA(str1), #str1, nIO, 0 ) ------------┐
_ = C.WriteFile( P1, Buf, 8*4, nIO, 0 )
_ = C.WriteFile( P1, charA(str3), #str3, nIO, 0 )
C.Sleep(100) ----- ダミー処理時間
-- シグナル状態チェック -- on 迄
repeat until band( C.WaitForSingleObject( E1, 1 ), 2 ) == 0
----- 結果受信
_ = C.ReadFile( P1, charA(Buf), 4097, nIO, 0 ) ------------┘
str = ffi.string( Buf, nIO[0] )
print( nIO[0], str )

C.FlushFileBuffers( P1 )
C.DisconnectNamedPipe( P1 )
C.CloseHandle( P1 )
print( 'End' ) -- デバッグ用
_=io.read(1) -- [Enter]キー入力待ち。
以上の組み合わせで、・・・
出来ました。


ここで、送信3回はイラナイかも?
上記では、
2回目のバイナリデータと、3回目の実行文の2回送信で十分?


なお、
以前(2017-02-03)の記事「クライアント/サーバ:PIPE 1本で双方向+EVENT」で書いた、
サブプログラムcdef_PIPE_Event_SUB.luaには、若干追加した。
結果は、以下:
------------------------ cdef_PIPE_Event_SUB.lua

charA = |s| ffi.cast( 'char*', s )
C = ffi.C; band = bit.band

Buf = ffi.new('uint8_t[4097]')
nIO = ffi.new('uint32_t[1]')

ffi.cdef[[
typedef unsigned int DWORD;

void Sleep( int MilliSeconds );

// ----- PIPE 用
int CreateNamedPipeA(
char* lpName, // パイプ名
DWORD dwOpenMode, // パイプを開くモード
DWORD dwPipeMode, // パイプ固有のモード
DWORD nMaxInstances, // インスタンスの最大数
DWORD nOutBufferSize, // 出力バッファのサイズ
DWORD nInBufferSize, // 入力バッファのサイズ
DWORD nDefaultTimeOut, // タイムアウトの間隔
int lpSecurityAttributes ); // セキュリティ記述子

int ConnectNamedPipe( int hNamedPipe, int lpOverlapped );

int CreateFileA(
char* pszFileName, // ファイル名
DWORD dwAccess, // アクセス指定
DWORD dwShare, // 共有方法
int psa, // セキュリティ属性
DWORD dwCreatDisposition, // 動作指定
DWORD dwFlagsAndAttributes, // フラグと属性
int hTemplate ); // テンプレートファイル

int ReadFile( int hFile, char* lpBuffer,
DWORD nNumberOfBytesToRead,
void* lpNumberOfBytesRead,
int lpOverlapped );

int WriteFile( int hFile, char* pBuffer,
DWORD nNumberOfBytesToWrite,
void* lpNumberOfBytesWritten,
int lpOverlapped );

int FlushFileBuffers( int hFile );
int DisconnectNamedPipe( int hNamedPipe );
int CloseHandle( int hObject );

// ----- Event 用
int CreateEventA(
int lpEventAttributes, // セキュリティ記述子
int bManualReset, // リセットのタイプ
int bInitialState, // 初期状態
char* lpName ); // イベントオブジェクトの名前

int OpenEventA(
int dwDesiredAccess, // アクセス権
int bInheritHandle, // 継承オプション
char* lpName ); // イベントオブジェクトの名前

int SetEvent( int hEvent );
int ResetEvent( int hEvent );

int WaitForSingleObject(
int hHandle, // オブジェクトのハンドル
int dwMilliseconds ); // タイムアウト時間:ミリ秒(ms)単位
]]


本日はここまで。


クライアント/サーバ学習は続く?


見ていただいた序でとは厚かましい限りですが、
お帰りに投票して頂けるとなお嬉しいです。 ⇒ blogram投票ボタン


170119
関連記事
スポンサーサイト

コメントの投稿

管理者にだけ表示を許可する

おきてがみ/blogram
blogram投票ボタン



おきてがみ

最新記事
カレンダー
09 | 2017/10 | 11
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 - - - -
月別アーカイブ
カテゴリ
最新コメント
検索フォーム
リンク
プロフィール

<紙>

Author:<紙>
ようこそ。
「パソコンヲタクの雑記帳」
もろもろなことを綴っています。
パソコン ヲタクってねくら?
画像は kami でなく kani です。

カウンター(fc2、i2i) /Google Analytics


i2i(from 2010-08-24)
Total =
Today  =  
Yesterday=
アンチエイジング

Google Analytics
ブックマーク