Java:call_Lua51 似非モジュール

2017-04-29 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-04-28)の記事「Java 学習:jnr-ffi 導入」で書いた如く、

  jnr-ffiが使えた。

ならばと、

SpiderMonkey:call_Lua51 似非モジュール

Python:call_Lua51 似非モジュール

に対抗して、
jnr-ffi を使った Java による call_Lua51 に挑戦。


非常に参考になったのは、
「今日もプログラミング」サイトの記事:
jnr-ffiでJavaからCのポインタを使う

その他本家のドキュメント(バージョン違いだが):
Java Platform, Standard Edition 6.0 API 仕様


悪戦苦闘した結果、出来たのは:
/* ----- Java_call_Lua51.java ----- */

import jnr.ffi.LibraryLoader; // 全4Dir必要

import java.nio.ByteBuffer; // これらも必要
import jnr.ffi.Pointer;
import jnr.ffi.Runtime;
import jnr.ffi.provider.jffi.ArrayMemoryIO;

/* ================================ */

public class Java_call_Lua51{ // 名前はファイル名と同じ

/* ------------------------------ */
public static interface libC { // この名前は適切に
int luaL_newstate( ); // 呼出関数のプロトタイプ
void luaL_openlibs( int L );
int lua_gettop( int L );
int lua_type( int L, int index );

int luaL_loadfilex( int L, String fname, String mode);
int lua_pcall( int L, int nargs, int nresults, int msgh );

void lua_getfield( int L, int i , String name );
void lua_pushinteger(int L, int n);
void lua_pushlightuserdata( int L, Pointer p ); // 'void*'
String lua_pushstring( int L, String s);

boolean lua_isstring( int L, int index );
String lua_tolstring( int L, int index, int len );
void lua_settop( int L, int m ); // m == -(n) - 1

void lua_close( int L );
}
/* ------------------------------ */

public static void main(String[] args) { // これは固定

// int IT[] = { 1, 2, 3, 4, 5, 0 };
// に相当するのは:
Pointer IT = Pointer.wrap(Runtime.getSystemRuntime(),ByteBuffer.allocateDirect(6*4).order(Runtime.getSystemRuntime().byteOrder()));
IT.putInt(0,1); IT.putInt(4,2); IT.putInt(8,3); IT.putInt(12,4);
IT.putInt(16,5); IT.putInt(20,0);

// double DT[] = { 1.1, 2.2, 3.3, 4.4, 5.5 };
// に相当するのは:
Pointer DT = Pointer.wrap(Runtime.getSystemRuntime(),ByteBuffer.allocateDirect(5*8).order(Runtime.getSystemRuntime().byteOrder()));
DT.putDouble(0,1.1); DT.putDouble(8,2.2); DT.putDouble(16,3.3);
DT.putDouble(24,4.4); DT.putDouble(32,5.5);

// IT[5] = DT;
// に相当するのは:
IT.putInt(20,(int)DT.address());

// Lua51 ( LuaJIT ) で実行するコード

String ST = "print('Lua5.1---');" +
"print(2+5);" +
"print( math.sin(1.0) )" +
"require'lfs'; print( lfs.currentdir() )" +
"print(IT[2]);" +
"DT=DblA(IT[5]); print(DT[3])" +
"IT[0]=999; SV='ok!'";


libC lua = LibraryLoader.create(libC.class).load("lua51");


int L = lua.luaL_newstate();
lua.luaL_openlibs(L);

int z = lua.luaL_loadfilex(L, "Lua51_Gen.lua", "bt" );

z = lua.lua_pcall(L, 0, 0, 0 ); // script を実行しておく

lua.lua_getfield( L, -10002, "Exec" ); // 呼び出す関数

// lua.lua_pushinteger( L, IT ); // 第1引数:lua_Integer
lua.lua_pushlightuserdata( L, IT ); // 第1引数: 'void*'

lua.lua_pushstring( L, ST ); // 第2引数:Lua5.1 での実行文

if (lua.lua_pcall(L, 2, 1, 0) != 0) { // 引数 2 個, 戻り値 1 個
System.out.println( "cannot exec. \r\n" ); // ---- 中で、実行
System.exit(0);
}

if( lua.lua_isstring(L, -1)) {
String SV = lua.lua_tolstring(L, -1, 0); // 戻り値
SV = SV.substring(0,SV.indexOf("\0"));
System.out.println( SV ); // ----- 'OK'~
}

lua.lua_settop(L, -2); // lua_pop(L,1); 戻り値を pop

lua.lua_close( L );

System.out.println( IT.getInt(0) );
}
}
でしょうか。

これをコンパイルするには:
javac  -cp  .;C:/_kami_  Java_call_Lua51.java
そして、実行するには:
java  -cp  .;C:/_kami_  Java_call_Lua51
だが、
「lua51.dll」「Lua51_Gen.lua」「lfs.dll」
も必要。

出来た!!!


今回学習したこと:

1.配列 IT を使いたいときは、
Java の配列: int IT[] = { 1, 2, 3, 4, 5, 0 };
ではダメ。
そして、
  import java.nio.ByteBuffer;
  import jnr.ffi.Pointer;
  import jnr.ffi.Runtime;
  import jnr.ffi.provider.jffi.ArrayMemoryIO;
を追加。


2.IT は、ポインタで宣言する:
バイト配列で、little エンディアンで、allocateDirect で。
つまり、
Pointer IT = Pointer.wrap(Runtime.getSystemRuntime(), ByteBuffer.allocateDirect(12).order(Runtime.getSystemRuntime().byteOrder()));
そして、
値の設定は、バイト位置指定の 'putInt'
  IT.putInt(0, 60000);
  IT.putInt(8, 8000);
とか。
取得は、
  IT.getInt(8)
とか。( IT[2] 相当 )


3.double 配列でも、やはり ByteBuffer を使うこと。


4.IT[5]=DT の様に、
DT配列の先頭アドレスを(intとして)IT配列の格納するには:

   IT.putInt( 20, (int)DT.address() );


5."Lua51_Gen.lua"の第1引数は、
  'lua_Integer' じゃなくて正しくポインタで。

  // lua.lua_pushinteger( L, IT ); // 第1引数:lua_Integer
  lua.lua_pushlightuserdata( L, IT ); // 第1引数: 'void*'


本日はここまで。


Java ( JNR-FFI ) 学習は続く。


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


170327-29
関連記事
スポンサーサイト

コメントの投稿

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

おきてがみ/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
ブックマーク