PyClient:LuaPy_GSL モジュールのラッパー

2017-02-27 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-02-26)の記事「LuaPy_GSL モジュール:格納場所」までで、
以前(2017-02-19)書いた記事「LuaPy_GSL モジュールで SymPy」の如く、
自作モジュール“LuaPy_GSL.lua”が完成の域に達した?

そこで、
そもそもの発端であった
以前(2017-01-23)の記事「クライアント/サーバ:プロセス間通信
に答えられるように“LuaPy_GSL モジュール”のラッパーとして、
PyClient サブを作った。
手始めなので、名前は取り敢えず“SUB.lua”とした。

作ったのは:
-------------------------- SUB.lua
local Py = require'LuaPy_GSL'
-------------------------------

Py.PyIni( 'SUB_LuaPy_GSL_Gen' ) -- Python 初期化済みに。
IT = ffi.new( 'int32_t[40]' ) -- 序でに定義。
SV = ffi.new( 'uint8_t[4097]' )

-------------------------------

function Py_Exec( str_ ) -- これが PyClient 相当???
IT[0] = #str_ + 1
Py.PyFun( 'Exec', IT, str_, SV )
return ffi.string( SV )
end

function Py_SymPy( str_ ) -- SymPy 用*****
local st = 'from sympy import *;var("a:z");SV=str( '..str_..' );\n'
IT[0] = #st + 1
Py.PyFun( 'Exec', IT, st, SV )
return ffi.string( SV )
end

function Py_End()
Py.PyFin() -- Python ファイナライズ
end
こんなもの。

これを使ったテストメイン(汎用):
------------------- test_use_SUB_Gen.gsl

require'SUB' -- IT[40], SV[4097] 定義済み
--------------------------------

----- Python での実行文
ST = [[
DT=doubleA(IT[1]); DV=doubleA(IT[2])
DV[0]=DT[3]; print DV[0],DT[3]
SV='HOGE'+str(DV[0])
]]
--------------- テスト用データ
DT = ffi.new( 'double[10]', 50.5, 60.5, 70.5, 80.5 )
DV = ffi.new( 'double[10]' )

--------------------------------
IT[1]=Int(DT); IT[2]=Int(DV) -- IT[0] は予約済
ss=Py_Exec( ST ) ------- これが、PyClient ???
Py_End()

print( DV[0],DV[1] ) --- 戻り値
print( ss ) --- 戻り文字列
これで、・・・・・
OK

続けてもう1つ。
SymPy を使った例:
------------------- test_use_SUB_SymPy.gsl
require'SUB' -- IT[40], SV[4097] 定義済み
--------------------------------

----------------- サンプル1
ss=Py_SymPy'diff( x**3+3*x**2+2, x, 1 )' -- 'x' で、1回微分
print( ss ) -- 3*x**2 + 6*x
---------------- サンプル2
ss=Py_SymPy'solve( x**2+4*x+a, x )' -- 引数1を引数2で解く
print( ss ) -- [-sqrt(-a + 4) -2, sqrt(-a + 4) -2]
----------------- サンプル3
ss=Py_SymPy'diff( sin(x), x, 2 )' -- 'x' で、2回微分
print( ss ) -- -sin(x)

Py_End()
これの方が“PyClient”っぽい???

出来た。


本日はここまで。


PyClient ( Lua / GSL Shell) 学習は続く。


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


170202
スポンサーサイト

LuaPy_GSL モジュール:格納場所

2017-02-26 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
先日(2017-02-17)の記事「LuaPy_GSL モジュール化」では、

  ・・・・・
  ・・・・・
  'python27.lib'、'LuaPy_GSL.lua'、'SUB_LuaPy_GSL_Gen.py'
  は、何処に置いておけばイイのか?
  3つともメインの'test_use_LuaPy_GSL.gsl'と同じ処に置けばイイけど。
  ・・・・・
  ・・・・・

等と書き、保留にしていた。


やっと、確定した。

結論としては、・・・・・

'python27.lib' ・・・ これは、“ライブラリ”扱いですね。

'LuaPy_GSL.lua'・・・ これは、“モジュールですね。

そうすると、
昨年(2016-03-30)の記事「GSL Shell 学習:モジュール/ライブラリ格納場所
で書いた通り。

  ・・・・・
  ・・・・・
  この「D:/TOOL/Lua」を「X」とすると、
  ・・・・・
  ・・・・・
  “モジュール”は、「X/gsl-shell/gsl-shell/」に格納する。
  ・・・・・
  ・・・・・
  一方、“ライブラリ”は、「X/gsl-shell/」に格納する。
  ・・・・・
  ・・・・・

に従う。



では、
'SUB_LuaPy_GSL_Gen.py'
は何処に?

モジュール 'LuaPy_GSL.lua'
の中身は、
・・・・・
・・・・・
function Py.PyIni( m ) -- int PyIni( char* m )
py.Py_Initialize()
pName = py.PyString_FromString( charA(m) )
pModule = py.PyImport_Import( pName )
pDict = py.PyModule_GetDict( pModule )
return 0;
end
・・・・・
・・・・・
と書いている。
つまり、'PyImport_Import(~)'
と云うことは、Python で import するもの???


こんな記事が見つかった:
Pythonのimportについてまとめる

  ・・・・・
  ・・・・・
  読み込み時に検索する範囲

  1.実行ディレクトリと同ディレクトリ
  2.カレントディレクトリ
  3.環境変数「PYTHONPATH」に列挙したディレクトリ
  4.sys.pathに含むディレクトリ
  ・・・・・
  ・・・・・


そうすると、
この中の4番目がよろしい?

つまり、(Python じゃないけど)GSL Shell のパス:
前記「X/gsl-shell/」に格納する。
ことで、
一件落着ダ。


本日はここまで。


LuaPy_GSL 学習は続く?


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


170128

タイマー:OpenCV 版

2017-02-24 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-02-22)の記事「タイマー:IupTimer 版」では、
IUP(Portable User Interface) には、IupTimer があるので、
Win32API に頼らずに タイマー 機能が使えた。


今回は、
OpenCV”で窓を出している状況で、
“タイマー”機能を使うには?
について学習。

“OpenCV”には、IupTimer の様な関数が無い?
なので、SetTimer を使う?

こんな感じ:
----------------------- test_Timer_OpenCV.gsl
cv2 = require'cv2'
NULL=voidA(0)
ffi.cdef[[
typedef void ( __stdcall* T_Proc )( void* hWnd, int Msg, int id, int time );
int SetTimer( void* hWnd, // window handle
int nIDEvent, // timer ID
int uElapse, // time-out value ( ms )
void* func ); // callback function
]]
-----------------------------------------
TCB = ffi.cast( 'T_Proc', function( a, b, c, d )
i=i+1; print( i, a, b, c, d ) -- i, NULL, 275, aaa, time
end )
i=0
aaa=ffi.C.SetTimer( NULL, 0, 200, TCB )
print(aaa)

img = cv2.cvCreateMat( 2, 2, 0 )
cv2.cvNamedWindow( charA('dmy'), 0 )

cv2.cvShowImage( charA('dmy'), img )
cv2.cvWaitKey(0)

cv2.cvDestroyAllWindows() -- 後処理
print( i ) -- 確認
でしょうか?


でも、いずれ
-- ・・・・・
-- ・・・・・
while true do
cv2.cvShowImage( charA('dmy'), img )
cv2.cvWaitKey(50)
-- ・・・・・
-- ・・・・・
end
-- ・・・・・
-- ・・・・・
の様に、
(例えば、50mSの)インターバルでループするものなので、
そのループ内で(コールバック相当の)関数を呼べばよい。
つまり、
改めて“タイマー”機能を使う必要が無いかも。


本日はここまで。


タイマー 学習は続く?


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


170129,0202

タイマー:IupTimer 版

2017-02-22 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-02-20)の記事「タイマー:Win32 API 版」では、
そもそも、
IUP(Portable User Interface) の IupTimer を見つけていたのに、
(何故か) MSDN を見に行き:SetTimer 関数 - MSDN
SetTimer に移ってしまった。


今回は、
本流に戻って、IupTimer によるコードを書いてみた。

結論は、以下:
----------------------- test_Timer_Min_IupTimer.gsl
local Iup = require'IUP'
Iup.Open( 0 )
NULL=voidA(0)

ffi.cdef[[
Ihandle* IupTimer(void); // [IUP.lua] に追加
]]
local iup = ffi.load('iup') -- [IUP.lua] に追加

-------------------------------------------------
TCB = ffi.cast( 'Icallback', function( n )
if n==timer1 then
i=i+1; print( i )
end
return -2
end )
i=0
timer1=iup.IupTimer() -- <=== これ
print(timer1) -- Ihandle_

Iup.SetAttribute( timer1, 'TIME', '200' ) -- インターバル ( mS )
Iup.SetAttribute( timer1, 'RUN', 'YES' )
Iup.SetCallback ( timer1, 'ACTION_CB', TCB )

dlg = Iup.Dialog( NULL ) -- 最低限の窓
Iup.SetAttribute( dlg, 'SIZE', '35x16' )
Iup.Popup( dlg, 0, 0 ) -- 窓左上隅位置
Iup.Close()

print( i ) -- 確認の為
これで使えた。


本日はここまで。


タイマー 学習は続く。


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


170123,29,0202

タイマー:Win32 API 版

2017-02-20 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
ふとしたことから、
IUP(Portable User Interface)”の、
IDLE_ACTION」ページの一番下から、
IupTimer」を見つけた。

 IupTimer
 Creates a timer which periodically invokes a callback when the time is up.
=== ( Google 翻訳 )
 タイムアップ時に定期的にコールバックを呼び出すタイマーを作成します。

それで、
(何故か) MSDN を見に行った:
SetTimer 関数 - MSDN - Microsoft

 SetTimer
 指定されたタイムアウト値を持つ 1 個のタイマを作成します。
 ・・・・・
 ・・・・・
 ・・・・・
 ・・・・・
  (一番下)
 参照
 KillTimer, , TimerProc,

から、
TimerProc」をみた。

以上から、タイマーについて学習した?
ので、
GSL Shell で、一本作ってみた:

“キーボードからの1文字入力待ち”の間、
200mS 間隔でカウントアップして印字する。
-------------------------- test_Timer.gsl
NULL = ffi.cast( 'void*', 0 )
ffi.cdef[[
typedef void ( __stdcall* T_Proc )( void* hWnd, int Msg, int id, int time );
int SetTimer( void* hWnd, // window handle
int nIDEvent, // timer ID
int uElapse, // time-out value ( ms )
void* func // callback function
);
]]
------------------------------------------------------------
TCB = ffi.cast( 'T_Proc', function( a, b, c, d )
i=i+1
print( i, a, b, c, d ) -- i, hWnd: NULL, 275, aaa, time
end )
i=0
aaa=ffi.C.SetTimer( NULL, 0, 200, TCB )
print(aaa)

_=io.read(1)

print( i )
の様なもの。

でも、これではタイマーが働いていない???


ハタと気が付いた。

  hWnd
  タイマに関連付けるべきウィンドウのハンドルを指定します。
  このウィンドウは、呼び出し側のスレッドが所有しているもの
  でなければなりません。
  NULL を指定すると、どのウィンドウにも関連付けられていない
  タイマが作成され、nIDEvent パラメータは無視されます。

とあるのだが、

  どの窓にも関連付けられていない

とは云っても、“何かしらの窓”が必要なのでは???


そこで、以下の様にメッセージボックス表示を追加してみた:
-------------------------- test_Timer.gsl
charA = |s| ffi.cast( 'char*', s )
NULL = ffi.cast( 'void*', 0 )
ffi.cdef[[
int MessageBoxA( int, char*, char*, int );

typedef void ( __stdcall* T_Proc )( void* hWnd, int Msg, int id, int time );
int SetTimer( void* hWnd, // window handle
int nIDEvent, // timer ID
int uElapse, // time-out value ( ms )
void* func // callback function
);
]]
------------------------------------------------------------
TCB = ffi.cast( 'T_Proc', function( a, b, c, d )
i=i+1
print( i, a, b, c, d ) -- i, hWnd: NULL, 275, aaa, time
end )
i=0
aaa=ffi.C.SetTimer( NULL, 0, 200, TCB )
print(aaa)

ffi.C.MessageBoxA( 0, charA('実行中'), charA('Timer'), 0 )

print( i )
の様に。

これだと、正常(意図した通り)に動きました。


本日はここまで。


タイマー 学習は続く。


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


170123,29

LuaPy_GSL モジュールで SymPy

2017-02-19 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-02-17)の記事「LuaPy_GSL モジュール化」で作った、
LuaPy_GSL.lua と、SUB_LuaPy_GSL_Gen.py を使って
SymPy の例を作ってみた。
主目的は、戻り文字列の動作確認。


テストプログラムは、test_use_LuaPy_GSL_SymPy
------------------------- test_use_LuaPy_GSL_SymPy.gsl

local Py = require'LuaPy_GSL'

------------------------------------------------
------------------------------------------------

Py.PyIni( 'SUB_LuaPy_GSL_Gen' ) -- Python 初期化

--------------- インタフェース情報
IT = ffi.new( 'int32_t[9]' )
SV = ffi.new( 'uint8_t[?]', 1000 )

----- 以下が、実行文群
-------------------------- サンプル1
ST = [[
from sympy import *
var("a:z")
SV=str( diff( x**3+3*x**2+2, x, 1 ) ) # 'x' で1回微分
]]
IT[0]=#ST+1
Py.PyFun( 'Exec', IT, ST, SV )
print( ffi.string( SV ) )

-------------------------- サンプル2
ST = [[
from sympy import *
var("a:z")
SV=str( solve( x**2+4*x+a, x ) ) # 引数1を引数2で解く
]]
IT[0]=#ST+1
Py.PyFun( 'Exec', IT, ST, SV )
Py.PyFin() -- Python ファイナライズ

print( ffi.string( SV ) )
_ = io.read(1)
これでテスト。

結果:

3*x**2 + 6*x
[-sqrt(-a + 4) - 2, sqrt(-a + 4) - 2]

と表示された。
OKダ。


本日はここまで。


LuaPy_GSL 学習は続く?


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


170122,28

LuaPy_GSL モジュール化

2017-02-17 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-02-15)の記事「LuaPy_gsl 経由で使う汎用 Python サブ」では、

呼出側 Lua プログラムで使う Python サブを汎用化してみた。

一応の完成?を見たので、
LuaPy_GSL をモジュール化した。
(LuaPy_gsl を LuaPy_GSL に改めた)


その前に、Lua-Python インタフェース を見直した。

呼ばれる Python サブを SUB_LuaPy_GSL_Gen.py とし、
引数を3つにした。
1つだけ定義されている関数は変わらず Exec のまま。

以前(2016-07-04)の記事「LuaPy.dll 改訂」で書いた“LuaPy_1.dll”に相当する
Lua モジュールは、LuaPy_GSL.lua とした。


これで、任意の GSL Shell プログラムでは、
LuaPy_GSL.lua 経由で、SUB_LuaPy_GSL_Gen.py を呼ぶ。


3つの引数について:

第1(IT):整数(int)型データの配列
第2(ST):実行したい Python ソーステキスト文字列データ
第3(SV):Python 実行結果の文字列データ格納領域

そして、
前回は固定(最大文字列)サイズだった、ST の文字列長は、
可変長として、IT[0] で受け渡す。
IT[1]~ は、直接 整数データ配列とするか、
整数/実数 任意のデータ配列へのポインタ(これも整数)とする。


そうすると、SUB_LuaPy_GSL_Gen.py は:
# -*- coding: utf-8 -*-

import sys ##### この部分は Tkinter つまり matplotlib 用
w=sys.path
for k in range(len(w)):
if w[k].find('Lib')>0: ww=w[k]; break
sys.path.append(ww+'/lib-tk')
# ----------------------------------
import ctypes as ct
import numpy as np

def IntA(x):
return ct.cast( x, ct.POINTER(ct.c_long) )
def doubleA(x):
return ct.cast( x, ct.POINTER(ct.c_double) )
def np_data( x ):
return ct.cast( id(x), ct.POINTER(ct.c_long) ) [2]
####################################
def Exec( IT_, ST_, SV_ ):
IT = IntA(IT_); leng = IT[0]
ST = ct.create_string_buffer(leng)
_ = ct.cdll.msvcrt.memcpy( ST, ST_, leng )

SV='nil'; exec( ST.value )

_ = ct.cdll.msvcrt.memcpy( SV_, SV, len(SV)+1 )
return 0
でしょうか。
最初の def 3つは、汎用で定義しておく。

それから、LuaPy_GSL.lua は:
local Py = { }                --- LuaPy_GSL.lua
local py = ffi.load( 'python27' )
-----------------------------------
charA = |x| ffi.cast( 'char*', x )
voidA = |x| ffi.cast( 'void*', x )
Int = |x| ffi.cast( 'int32_t', x )
NULL = voidA(0)

ffi.cdef[[
void Py_Initialize( void );
void* PyString_FromString( char* );
void* PyImport_Import( void* );
void* PyModule_GetDict( void* );
void* PyDict_GetItemString( void*, char* );
void* PyTuple_New( int );
void* PyInt_FromLong( int );
void PyTuple_SetItem( void*, int, void* );
// void* PyObject_CallObject( void*, void* ); ----- これを、
void* PyObject_CallFunctionObjArgs( void*, ... ); // これに。
int PyInt_AsLong( void* );
void Py_Finalize( void );
]]
----------------------------------------------------
function Py.PyIni( m ) -- int PyIni( char* m )
py.Py_Initialize()
pName = py.PyString_FromString( charA(m) )
pModule = py.PyImport_Import( pName )
pDict = py.PyModule_GetDict( pModule )
return 0;
end
------ 関数名、IT配列、str、戻りstr(要確保)
function Py.PyFun( fun, IT_, ST_, SV_ )
pFunc = py.PyDict_GetItemString( pDict, charA(fun) )
pA0 = py.PyInt_FromLong( Int(IT_) )
pA1 = py.PyInt_FromLong( Int(charA(ST_)) )
pA2 = py.PyInt_FromLong( Int(SV_) )
pValue = py.PyObject_CallFunctionObjArgs( pFunc, pA0, pA1, pA2, NULL )
return py.PyInt_AsLong( pValue )
end
function Py.PyFin( ) -- int PyFin( )
-- py.Py_DECREF( pArgs ) -- Py_DECREF はマクロ!使えない。
-- py.Py_DECREF( pValue ) -- 無くてもイイのかな?
-- py.Py_DECREF( pDict )
-- py.Py_DECREF( pModule )
-- py.Py_DECREF( pName )
py.Py_Finalize()
return 0;
end

return Py
で行ける?


早速、テストプログラムを1本作った:
------------------------ test_use_LuaPy_GSL.gsl

local Py = require'LuaPy_GSL'

-----------------------------------------
-----------------------------------------

Py.PyIni( 'SUB_LuaPy_GSL_Gen' ) -- Python 初期化

--------------- インタフェース情報
IT = ffi.new( 'int32_t[9]' )
DT = ffi.new( 'double[?]', 10, 50.5, 60.5, 70.5, 80.5 )
DV = ffi.new( 'double[?]', 10 )
SV = ffi.new( 'uint8_t[?]', 4097 )

----- 以下が、実行文群
ST = [[
DT=doubleA(IT[1]); DV=doubleA(IT[2])
DV[0]=DT[3]
print DV[0],DT[3]
SV='HOGE'+str(DV[0])
]]
------------------------------------
IT[0]=#ST+1; IT[1]=Int(DT); IT[2]=Int(DV)
Py.PyFun( 'Exec', IT, ST, SV )
Py.PyFin() -- Python ファイナライズ

print( DV[0],DV[1] )
print( ffi.string( SV ) )
_ = io.read(1)
これで、
一応のテストOK?


さて、
'python27.lib'、'LuaPy_GSL.lua'、'SUB_LuaPy_GSL_Gen.py'
は、何処に置いておけばイイのか?
3つともメインの'test_use_LuaPy_GSL.gsl'と同じ処に置けばイイけど。

これは、継続学習ダ。


本日はここまで。


LuaPy_GSL 学習は続く。


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


170122,28

LuaPy_gsl 経由で使う汎用 Python サブ

2017-02-15 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-02-13)の記事「LuaPy_gsl:GSL Shell による LuaPy.dll 相当品」で書いた、
呼出側 Lua プログラムで使う Python サブを汎用化してみた。


以前(2016-08-13)の記事「LuaPy 経由で使う汎用 Python サブ」では、
  ・・・・・
  ・・・・・
  この Python プログラムには、
  “Exec”関数一つだけ。

  それは、
  受け取った文字列を、“exec”文で実行するだけ。
  受け取る文字列は配列に格納されていて、
  その配列サイズも受け取る。

  つまり、こんなコード:
  ・・・・・
  ・・・・・
と云うことで、“Sub_LuaPy_Gen.py”を作ったが、
今回、再設計した。


やはり“Exec”関数一つだけ。
だが、引数は4つ:
第1 ( s1 ):受取文字列。これを exec() で実行する。
第2 ( d1 ):受取 double データ(配列)の先頭アドレス。
第3 ( d2 ):返却 double データ(配列)の先頭アドレス。
第4 ( s2 ):返却文字列。文字列データはここに格納する。

なお、第3、第4引数に関しては、
その領域は呼出側で用意しておく。
また、Python プログラムでは、
d1、d2、s2 それぞれの領域は、DT、DV、SV で参照する。


つまり、こんなコード:
# -*- coding: utf-8 -*-
# --- Sub_LuaPy_Gen_g.py
import sys ##### この部分は Tkinter つまり matplotlib 用
w=sys.path
for k in range(len(w)):
if w[k].find('Lib')>0: ww=w[k]; break
sys.path.append(ww+'/lib-tk')

import ctypes as ct
import numpy as np

def IntA(x):
return ct.cast( x, ct.POINTER(ct.c_long) )

def doubleA(x):
return ct.cast( x, ct.POINTER(ct.c_double) )

def np_data( x ):
return ct.cast( id(x), ct.POINTER(ct.c_long) ) [2]

###########################################

def Exec( s1, d1, d2, s2 ):
DT = doubleA( d1 ); DV = doubleA( d2 )
ST = ct.create_string_buffer(4097)
_ = ct.cdll.msvcrt.memcpy( ST, s1, 4096 )

SV='nil'; exec( ST.value )

_ = ct.cdll.msvcrt.memcpy( s2, SV, len(SV)+1 )
return 0
でしょうか。


これを使うサンプルコードについては、・・・・・

Python 2.7.x Documentation
オブジェクトプロトコル (object protocol)
で学習して、

引数をタプルで渡す PyObject_CallObject を使うよりも、
代わりに引数を個別の変数で渡す
PyObject_CallFunctionObjArgs を使った方が速いとか?

それで、
これを使ってみた:
--------------- tst_LuaPy_Gen_g.gsl
charA = |x| ffi.cast( 'char*', x )
voidA = |x| ffi.cast( 'void*', x )
Int = |x| ffi.cast( 'int32_t', x )
NULL = voidA(0)

Py = ffi.load('python27')
ffi.cdef[[
void Py_Initialize( void );
void* PyString_FromString( char* );
void* PyImport_Import( void* );
void* PyModule_GetDict( void* );
void* PyDict_GetItemString( void*, char* );
void* PyTuple_New( int );
void* PyInt_FromLong( int );
void PyTuple_SetItem( void*, int, void* );
// void* PyObject_CallObject( void*, void* ); ----- これを、
void* PyObject_CallFunctionObjArgs( void*, ... ); // これに。
int PyInt_AsLong( void* );
void Py_Finalize( void );
]]
function PyIni( m ) -- int PyIni( char* m )
Py.Py_Initialize()
pName = Py.PyString_FromString( charA(m) )
pModule = Py.PyImport_Import( pName )
pDict = Py.PyModule_GetDict( pModule )
return 0;
end
function PyFun( f, p0, p1, p2, p3 ) --===============
pFunc = Py.PyDict_GetItemString( pDict, charA(f) )
pA0 = Py.PyInt_FromLong( p0 )
pA1 = Py.PyInt_FromLong( p1 )
pA2 = Py.PyInt_FromLong( p2 )
pA3 = Py.PyInt_FromLong( p3 )
pValue = Py.PyObject_CallFunctionObjArgs( pFunc, pA0, pA1, pA2, pA3, NULL )
return Py.PyInt_AsLong( pValue )
end
function PyFin( ) -- int PyFin( )
-- Py.Py_DECREF( pArgs ) -- Py_DECREF はマクロ (使えない)
-- Py.Py_DECREF( pValue ) -- 無くてもイイのかな?
-- Py.Py_DECREF( pDict )
-- Py.Py_DECREF( pModule )
-- Py.Py_DECREF( pName )
Py.Py_Finalize()
return 0;
end
-----------------------------------------

PyIni( 'Sub_LuaPy_Gen_g' ) -- Python 初期化

------------- インタフェース情報
DT = ffi.new( 'double[?]', 10, 50,60,70,80 )
DV = ffi.new( 'double[?]', 10 )
SV = ffi.new( 'uint8_t[?]', 4097 )

----- 以下が、Python 実行文群
ST = [[
DV[0]=DT[3]
print DV[0],DT[3]
SV='hoge'
]]
---------------------------------

PyFun( 'Exec', Int(charA(ST)), Int(DT), Int(DV), Int(SV), NULL )
PyFin() -- Python ファイナライズ
print( DV[0], DV[1] )
print( ffi.string( SV ) )
_ = io.read(1)
こんな感じ。

実行出来た。


でも、前半の宣言部分が多すぎるナ。
モジュール化を考えよう。


本日はここまで。


LuaPy_gsl 学習は続く。


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


170122,26

LuaPy_gsl:GSL Shell による LuaPy.dll 相当品

2017-02-13 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
以前(2016-07-04)の記事「LuaPy.dll 改訂」では、
  ・・・・・
  ・・・・・
  先々月(2016-05-26)の記事「LuaPy.dll 作成
  で書いた、初版“LuaPy”即ち“LuaPy_0.dll”を機能拡張し、
  “LuaPy_1.dll”を作った。
  ・・・・・
  ・・・・・
と書いている。

この“LuaPy_1.dll”は、C言語で作っていたが、
相当品を GSL Shell で作れないか?
といろいろ学習した。


結果、
python.exeのある場所:
<紙>の場合は、D:/TOOL/WinPython32_2763/python-2.7.6/
ここにある python27.lib を使えば出来そうダ。


そこで、
上記 2016-07-04 の記事で書いた
“Sub_LuaPy_1.py”を使う“test_LuaPy_1.gsl”に相当するコードを、

“LuaPy_1.dll”を使わずに書いてみた。
(と云っても、代わりに“python27.lib”を使うことになるが)

----- tst_LuaPy_gsl.gsl : test_LuaPy_1.gsl 相当
-------------------------------------------------
charA = |x| ffi.cast( 'char*', x )
Int = |x| ffi.cast( 'int32_t', x )

Py = ffi.load('python27') -- 'python27.lib' を持ってくる
ffi.cdef[[
void Py_Initialize( void );
void* PyString_FromString( char* );
void* PyImport_Import( void* );
void* PyModule_GetDict( void* );
void* PyDict_GetItemString( void*, char* );
void* PyTuple_New( int );
void* PyInt_FromLong( int );
void PyTuple_SetItem( void*, int, void* );
void* PyObject_CallObject( void*, void* );
int PyInt_AsLong( void* );
void Py_Finalize( void );
]]
function PyIni( m ) -- int PyIni( char* m )
Py.Py_Initialize()
pName = Py.PyString_FromString( charA(m) )
pModule = Py.PyImport_Import( pName )
pDict = Py.PyModule_GetDict( pModule )
return 0;
end
function PyFun( f, s, p ) -- int PyFun( char* f, int s, void* p )
pFunc = Py.PyDict_GetItemString( pDict, charA(f) )
pArgs = Py.PyTuple_New( 2 )
pValue = Py.PyInt_FromLong( s )
Py.PyTuple_SetItem( pArgs, 0, pValue )
pValue = Py.PyInt_FromLong( Int(p) )
Py.PyTuple_SetItem( pArgs, 1, pValue )
pValue = Py.PyObject_CallObject( pFunc, pArgs )
return Py.PyInt_AsLong( pValue )
end
function PyFin( ) -- int PyFin( )
-- Py.Py_DECREF( pArgs ) -- Py_DECREF はマクロ!使えない。
-- Py.Py_DECREF( pValue ) -- 無くてもイイのかな?
-- Py.Py_DECREF( pDict )
-- Py.Py_DECREF( pModule )
-- Py.Py_DECREF( pName )
Py.Py_Finalize()
return 0;
end
-------------------------------------------------
p = ffi.new( 'int32_t[2]' )

print( PyIni( 'Sub_LuaPy_1' ) )

p[0]=5
print( PyFun( 'fun', 0, p ) )
print( PyFun( 'fun', 1, p ) )

p[0]=20
print( PyFun( 'fun2', 0, p ) )
print( PyFun( 'fun2', 1, p ) )

print( PyFin() )
こんな感じになった。

実行出来た。

この方式だと、
Cコンパイルの必要が無い!!!


本日はここまで。


LuaPy_gsl 学習は続く。


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


170121,26

IUP で GUI アプリ:コード改訂

2017-02-12 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
以前(2016-04-28)の記事「GSL Shell 学習:“IUP.lua”モジュール自作」では、
この自作した“IUP.lua”モジュールを使って、
その前(2016-04-26)の記事「GSL Shell 学習:IUP で GUI アプリ」のコードを書き直した。

それでも、
IupVbox や、IupHbox の順序を入れ替えたい場合、
コードの変更量が些か多いと感じる。

何とか、そこを簡単に出来ないかと考えた。

関数の引数はネストさせれたので、
無駄な定義を端折ることが出来た。

と云うことで、
以前のコードを改訂した。

local Iup = require'IUP'
Iup.Open( 0 ) ---------- これ必須!!!
NULL=voidA(0)
--------------- BUTTON の 'ACTION' コールバック関数
Bcb = ffi.cast( 'Icallback', function( z )
tt1 = ffi.string( Iup.GetAttribute( txt1, 'VALUE') )
tt2 = ffi.string( Iup.GetAttribute( txt2, 'VALUE') )
print( 'Button Clicked' )
print( tt1 )
print( tt2 )
return -2
end )
---------------------------------------
s7=' '; s14=s7..s7 -- 7文字、14文字空白

txt1 = Iup.Text('')
txt2 = Iup.Text('')
btn1 = Iup.Button(' Go ', '')

dlg = Iup.Dialog( Iup.Vbox(
Iup.Hbox( Iup.Label(s7), NULL ),
Iup.Hbox( Iup.Label(s7), Iup.Label('TEXT1 : '), txt1, NULL ),
Iup.Hbox( Iup.Label(s7), Iup.Label('TEXT2 : '), txt2, NULL ),
Iup.Hbox( Iup.Label(s7), NULL ),
Iup.Hbox( Iup.Label(s14), btn1, NULL ), NULL )
)
Iup.SetAttribute( dlg, 'SIZE', '100x90' )
Iup.SetAttribute( dlg, 'TITLE', 'test' ) -- 窓のタイトル
Iup.SetCallback( btn1, 'ACTION', Bcb )

Iup.Popup( dlg, 350, 250 ) -- 窓表示左上隅
Iup.Close() -- <===右上[X]で終了。
---------------------------------------
print( tt1 )
print( tt2 )
_ = io.read(1) -- [Enter]キー入力待ち。
これで、
それなりにスッキリ?した。


今後は、これを雛形にしよう。


本日はここまで。


Lua ( GSL Shell ) 学習は続く。


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


170118,26

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

Lua/Lua:PIPE 1本で双方向+EVENT

2017-02-08 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-02-06)の記事「Lua から Python:PIPE 1本で双方向+EVENT」で、
以前(2017-02-03)の記事「クライアント/サーバ:PIPE 1本で双方向+EVENT」で書いた、
クライアント側「Master_Client.gsl」のコードを変えた。

なので、
サーバ側 「Slave_Server.gsl」も変更する。
ある意味、Python からの逆移植?

結果のコード:
---------- Slave_1.gsl
require'cdef_PIPE_event_SUB'
print( 'Start Slave' ) -- デバッグ用
----- マスタ(クライアント)から呼ばれ:
-- イベントオブジェクト作成
EVN = C.CreateEventA( 0, 1, 0, charA('EVENT1') )
-- イベントオブジェクト取得
E1 = C.OpenEventA( 0x001F0003, 0, charA('EVENT1') )

C.SetEvent( E1 ) -- シグナル on に
----- PIPE オープン
P1 = C.CreateFileA(charA('\\\\.\\pipe\\PIPE1'), 3, 0, 0, 3, 0x80, 0 )

------------------------------------ 処理:無限ループ:
while true do
-- シグナル状態チェック -- off 迄
repeat until band( C.WaitForSingleObject( E1, 1 ), 2 ) ~= 0
-- リクエスト受信
rtn=C.ReadFile( P1, charA(Buf), 4097, nIO, 0 ) ------┐
if rtn==0 then break end

str=ffi.string(Buf,nIO[0])
print( nIO[0], str )
if str=='e' then break end

C.Sleep(500) ------ ダミー処理

-- シグナル on にして、結果送信
C.SetEvent( E1 )
rtn=C.WriteFile( P1, charA(str..'HOGE'), nIO[0]+4, nIO, 0 ) ------┘
end
C.CloseHandle( P1 )
print( 'End Slave' ) -- デバッグ用
_=io.read(1)
そうすると、
マスター側は、実質“Master_1_Py.gsl”と変わらないが、
------------- Master_1.gsl
require'cdef_PIPE_Event_SUB'
print( 'Start' ) -- デバッグ用
-- パイプを作成
P1 = C.CreateNamedPipeA( charA("\\\\.\\pipe\\PIPE1"), 3, 0, 1, 0, 0, 100, 0 )
-- サーバー立ち上げ
os.execute('start Slave_1.gsl')
-- PIPE オープン待ち
rtn=C.ConnectNamedPipe( P1, 0 )

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

----- シグナル off に:初期化
C.ResetEvent( E1 )
------------------------------------ 主処理:
while true do
print( 'Input: e for END' )
str = io.read() -- キー入力

-- シグナル off にして、リクエスト送信
C.ResetEvent( E1 )
rtn = C.WriteFile( P1, charA(str), #str, nIO, 0 ) --------------------------┐
if str == 'e' then break end

C.Sleep(100) ----- ダミー処理時間

-- シグナル状態チェック -- on 迄
repeat until band( C.WaitForSingleObject( E1, 1 ), 2 ) == 0
----- 結果受信
rtn=C.ReadFile( P1, charA(Buf), 4097, nIO, 0 ) --------------------------┘
str=ffi.string(Buf,nIO[0])
print( nIO[0], str )
end
C.FlushFileBuffers( P1 )
C.DisconnectNamedPipe( P1 )
C.CloseHandle( P1 )
print( 'End' ) -- デバッグ用
_=io.read(1)
これでOK


本日はここまで。


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


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


170113

Lua から Python:PIPE 1本で双方向+EVENT

2017-02-06 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-02-05)の記事「Lua/Python:PIPE 1本で双方向+EVENT」では、方式の変更が必要になった。


それで、
再設計を行った。


クライアント側コード:
------------- Master_1_Py.gsl
require'cdef_PIPE_Event_SUB'
print( 'Start' ) -- デバッグ用
-- パイプを作成
P1 = C.CreateNamedPipeA( charA("\\\\.\\pipe\\PIPE1"), 3, 0, 1, 0, 0, 100, 0 )
-- サーバー立ち上げ
os.execute('start Py_Slave_1.py')
-- PIPE オープン待ち
rtn=C.ConnectNamedPipe( P1, 0 )

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

----- シグナル off に:初期化
C.ResetEvent( E1 )
------------------------------------ 主処理:
while true do
print( 'Input: e for END' )
str = io.read() -- キー入力

-- シグナル off にして、リクエスト送信
C.ResetEvent( E1 )
rtn = C.WriteFile( P1, charA(str), #str, nIO, 0 ) ---------------------┐
if str == 'e' then break end

C.Sleep(100) ----- ダミー処理時間

-- シグナル状態チェック -- on 迄
repeat until band( C.WaitForSingleObject( E1, 1 ), 2 ) == 0
----- 結果受信
rtn=C.ReadFile( P1, charA(Buf), 4097, nIO, 0 ) ---------------------┘
str=ffi.string(Buf,nIO[0])
print( nIO[0], str )
end
C.FlushFileBuffers( P1 )
C.DisconnectNamedPipe( P1 )
C.CloseHandle( P1 )
print( 'End' ) -- デバッグ用
_=io.read(1)
ここで、
サブプログラム“cdef_PIPE_Event_SUB.lua”は、
クライアント/サーバ:PIPE 1本で双方向+EVENT」で定義したもの。

サーバ側コード:
# coding: utf-8
# ------------- Py_Slave_1.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);

# ------------------------------------ 処理:無限ループ:
while True:
# -- シグナル状態チェック -- off 迄
flg = win32event.WaitForSingleObject( E1, 0 )
while flg == 0: # -- シグナル on==0、off==258(初期状態)
flg = win32event.WaitForSingleObject( E1, 0 )
# -- リクエスト受信
data = win32file.ReadFile( P1, 4096 );
print data[1];
if data[1]=='e':
break;

time.sleep( 1 ) # ダミー時間待ち(秒数)
data = data[1] + "HOGE";

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

print( 'End Slave' ) # ----- デバッグ用
_=raw_input()

以上で、
“Master_1_Py.gsl”をダブルクリックで、・・・

OKですね。


本日はここまで。


“クライアント/サーバ”学習は続く。


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


170113

Lua/Python:PIPE 1本で双方向+EVENT

2017-02-05 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-02-03)の記事「クライアント/サーバ:PIPE 1本で双方向+EVENT」で、
  ・・・・・
  ・・・・・
  “Master_Client.gsl”をダブルクリックすると、・・・
  出来ました。
  ・・・・・
  ・・・・・
と、
GSL Shell 同士では、一応の完成を見た?ので、・・・


今度は、
サーバ側 Slave_Server.gsl を、Python に移植したい。

早速、
設計もそこそこに、コーディングに取りかかった。


だが、出だしで躓いた、

-- ・・・・・
-- ・・・・・
----- マスタ(クライアント)から呼ばれた:
-- イベントオブジェクト取得
E1 = C.OpenEventA( 0x001F0003, 0, charA('EVENT1') )
-- ・・・・・
-- ・・・・・
とあるが、・・・・・

Python には、
“イベントオブジェクト取得”に相当する関数が無い?

win32event にあるのは、

win32event.CreateEvent( None, 1, 0, 'EVENT1' )
# イベントハンドルを非シグナルで作成。

この“CreateEvent”関数だけ?
この関数で、
“イベントオブジェクト作成”&“イベントオブジェクト取得”
となる様ダ。


と云うことは、
“イベントオブジェクト作成”は、Python 側で!
そうすると、
“パイプの作成”は、GSL Shell 側で?


出直して来ます。


本日はここまで。


“クライアント/サーバ”学習は続く。


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


170112

クライアント/サーバ:PIPE 1本で双方向+EVENT

2017-02-03 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-02-01)の記事「クライアント/サーバ:PIPE 1本で双方向通信」に続いて、
イベントは無くても良さそう(?)だったが、
正統?“ハンドシェイク通信”とすべく、EVENT 同期を追加した。


その前に、
“プロトタイプ?”宣言をダラダラ書きたくないので、
サブプログラム化した:
----- 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]') ----- 実I/Oバイト数

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)単位
]]
これで、本体プログラムはスッキリする?


それで、
1.クライアント側からサーバ側を起動する様にする
   クライアント:Master_Client.gsl
   サーバ:Slave_Server.gsl
2.PIPE は、これまで通りサーバ側で作成し、
  EVENT は、クライアント側で準備する。
   イベント(signal)の初期値は、off とする。
3.signal 状態:
   クライアント側から送ったら、off
   サーバ側から送り返したら、on
4.サンプルコード:
   クライアント側でキーボード入力し、
   サーバに送信し、
   サーバ側では、文字列を加工し、
   クライアント側に送り返す。
   キー入力が 'e' で処理終了。

結果のコード:

クライアント側コード:
------------- Master_Client.gsl
require'cdef_PIPE_Event_SUB'
print( 'Start' ) -- デバッグ用
----- 初期化1:イベント準備
-- イベントオブジェクト作成
EVN = C.CreateEventA( 0, 1, 0, charA('EVENT1') )
-- イベントオブジェクト取得
E1 = C.OpenEventA( 0x001F0003, 0, charA('EVENT1') )

----- 初期化2:サーバー立ち上げ
os.execute('start Slave_Server.gsl')
-- 立ち上げ確認:シグナル状態チェック for PIPE Open
repeat until band( C.WaitForSingleObject( E1, 1 ), 2 ) == 0 -- on 迄
----- PIPE オープン
P1 = C.CreateFileA(charA('\\\\.\\pipe\\PIPE1'), 3, 0, 0, 3, 0x80, 0 )
-- シグナル off に:初期化
C.ResetEvent( E1 )

-------------------- 主処理:(無限)ループ
while true do
print( 'Input: e for END' )
str = io.read() -- キー入力

-- シグナル off にして、リクエスト送信
C.ResetEvent( E1 )
rtn = C.WriteFile( P1, charA(str), #str, nIO, 0 ) --------------┐

if str == 'e' then break end

C.Sleep(100) ----- ダミー処理時間

-- シグナル状態チェック -- on 迄
repeat until band( C.WaitForSingleObject( E1, 1 ), 2 ) == 0
----- 結果受信
rtn=C.ReadFile( P1, charA(Buf), 4096, nIO, 0 ) --------------┘
str=ffi.string(Buf,nIO[0])
print( nIO[0], str )
end
C.CloseHandle( P1 )
print( 'End' ) -- デバッグ用
_=io.read(1)


サーバ側コード:
------------- Slave_Server.gsl
require'cdef_PIPE_Event_SUB'
print( 'Start Server' ) -- デバッグ用
----- マスタ(クライアント)から呼ばれた:
-- イベントオブジェクト取得
E1 = C.OpenEventA( 0x001F0003, 0, charA('EVENT1') )

-- パイプを作成
P1 = C.CreateNamedPipeA( charA("\\\\.\\pipe\\PIPE1"), 3, 0, 1, 0, 0, 100, 0 )
-- シグナル状態にする。
C.SetEvent( E1 )
-- Client オープン待ち
rtn=C.ConnectNamedPipe( P1, 0 )

----- 無限ループ:
while true do
-- シグナル状態チェック -- off 迄
repeat until band( C.WaitForSingleObject( E1, 1 ), 2 ) ~= 0
-- リクエスト受信
rtn=C.ReadFile( P1, charA(Buf), 4097, nIO, 0 ) -------------┐
if rtn==0 then break end
str=ffi.string(Buf,nIO[0])
print( nIO[0], str )
if str=='e' then break end

C.Sleep(500) ------ ダミー処理時間

-- シグナル on にして、結果送信
C.SetEvent( E1 )
rtn=C.WriteFile( P1, charA(str..'HOGE'), nIO[0]+4, nIO, 0 ) -------------┘
end
C.FlushFileBuffers( P1 )
C.DisconnectNamedPipe( P1 )
C.CloseHandle( P1 )
print( 'End Server' ) -- デバッグ用
_=io.read(1)

これで、
“Master_Client.gsl”をダブルクリックすると、・・・
出来ました。


ですが、
マスター(クライアント)も、スレーブ(サーバ)も、
送信する前に、イベント(シグナル)を設定している!

この件、
精神衛生上、逆にしたかったのだが、
何故だか、正常に動作しなかった???
仕方なく、送信直前に設定することにした。


本日はここまで。


“クライアント/サーバ”学習は続く。


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


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



おきてがみ

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

<紙>

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

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


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

Google Analytics
ブックマーク