Lua - dll 連携:コールバック処理

2016-04-20 :  PCクリニック

本文の前に、
-・・・ -・-
現時点での blogramのランクインカテゴリは、
7、2、0、0、1、 0、0、0、0、0(40)で、換算ポイント 88pt 。
「Perl」「化学業界」「FM COCOLO」「グルコサミン」、
「Python」「Firefox」bg値変動のみ。
「C言語」「硝子業界」「e-radio」「FM青森」全く変化無し。
・-・ - -・

さて、本文。

“Lua”プログラムから“dll”を呼んで、更に“コールバック処理”も行う。

と云うことについてまとめた。


始めに、
<紙>の云う“Lua”についておさらい。

言語仕様は“Lua”「プログラミング言語 Lua」ベースで、
処理系は“LuaJIT”「LuaJIT : Just-In-Time Compiler (JIT) for the Lua …」で、
“GNU Scientific Library”の機能を追加した「The GSL Shell Project」である。
そして、
<紙>は「.gsl」拡張子を「gsl-shell」インタプリタに対応付けしている。

この環境では、
“FFI”機能を使って、
Lua プログラムから自作の dll を呼び出すことが出来る:
Lua 学習:LuaJIT の FFI 使用法」で書いている。

若干修正して、再度掲載:


呼び出したい「S.dll」は、gcc C言語で「S.c」ファイルを作り、
コメントに書いたコマンドで「S.dll」を作る---------------
//  S.dll のソース : S.c
// コンパイルは、 clang -shared -o S.dll S.c

int Add( int x, int y ){ return x+y; }
の様に(この例では実質1行)。

呼び出し側「M.gsl」は、
--  dll 呼び出しプログラム : M.gsl
-- require'ffi' は特に必要無し。

ffi.cdef[[
int Add( int, int );
]]
k_lib = ffi.load( 'S' )

print( k_lib.Add( 2, 3 ) ) -- 5 と出る。

_ = io.read(1) -- [Enter]キー入力待ち。
として「M.gsl」をダブルクリックで、実行出来る。


さて、
ここからが、本題。

それでは、
呼び出された「S.dll」から戻る前に、
「M.gsl」内部の関数を呼び出す。
即ち、“コールバック処理”の記述方法は?

「C言語ワンポイント講座 ・・・」の、
第3章 関数を指すポインタ
ページに、
  Sample list 3-1 関数を指すポインタ
が載っている。
キモは、
  double (*p)(double) = f1;
とある1行の様なコードですね。

このやり方をすれば出来ますネ。

上記メイン/サブを改訂。

「S.dll」用の「S.c」ファイルは---------------
//  S.dll のソース : S.c
// コンパイルは、 clang -shared -o S.dll S.c

int Add( int x, int y ){ return x+y; }

int AddX( double x, int y, void* fun ){
int(*p)(int,int)=fun; // fun はコールバック関数
int z = p( (int)x, y );
return 2*z;
}
の様にする。

呼び出し側は、
--  dll 呼び出しプログラム : M.gsl
-- require'ffi' は特に必要無し。

ffi.cdef[[
int Add( int, int );
typedef int ( __stdcall *Xcb ) ( int, int );
int AddX( double, int, Xcb );
]]
k_lib = ffi.load( 'S' )

-- k_lib.AddX からの CallBack 関数
Xcb = ffi.cast( 'Xcb', function( x, y )
return x+y
end )

print( k_lib.Add( 2, 3 ) ) -- 5 と出る。

print( k_lib.AddX( 2.9, 3, Xcb ) ) -- 10 と出る。

_ = io.read(1) -- [Enter]キー入力待ち。
として「M.gsl」をダブルクリックで、実行出来る。


なお、
上記「M.gsl」は、

“FFI”のドキュメント:「The LuaJIT Project」の「Extensions
にある「FFI Semantics」で、
  Explicitly convert to a callback via cast
のケースに従った。
これだと、
  cb:free()
の実行が必要?


もう一方の、
  Implicit conversion to a callback via function pointer argument
のケースの方式では、
--  dll 呼び出しプログラム : M.gsl
-- require'ffi' は特に必要無し。

ffi.cdef[[
int Add( int, int );
typedef int ( __stdcall *Xcb ) ( int, int );
int AddX( double, int, Xcb );
]]
k_lib = ffi.load( 'S' )

print( k_lib.Add( 2, 3 ) ) -- 5 と出る。

-- CallBack 関数
print( k_lib.AddX( 2.9, 3, function( x, y )
return x+y
end )
) -- 10 と出る。

_ = io.read(1) -- [Enter]キー入力待ち。
となりますネ。


本日はここまで。


Lua ( GSL Shell ) 学習は続く。


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


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

コメントの投稿

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

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



おきてがみ

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

<紙>

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

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


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

Google Analytics
ブックマーク