JNR-FFI :ImageJ プラグイン(Java)では使えない?

2017-04-30 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-04-29)の記事「Java:call_Lua51 似非モジュール」で書いた如く、
“jnr-ffi”を使えば、Java から LuaJIT を呼び出せた。


そもそも、
Java は、ImageJ のプラグイン作成用
としか(?)考えていない

そこで、
自作プラグイン・サンプルに、jnr-ffi を組み込んでみた。


昨年10月(2016-10-23)の記事「ImageJ 学習:プラグイン開発手順?」で作った:
「k_Java.java」をベースとした。

以下、太字部分を追加:
// ----- k_Java_FFI.java -----

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

import ij.*;
import ij.gui.*;
import ij.plugin.PlugIn;
import ij.process.*;
import java.awt.*;

public class k_Java_FFI implements PlugIn{

public static interface libC { // これは適切に
int Add( int a, int b ); // 呼出関数のプロトタイプ
}

public void run( String arg ){
// =========================

ImagePlus imp1 = IJ.getImage(); // var → ImagePlus
ImageProcessor ip1 = imp1.getProcessor(); // var → ImageProcessor
int xx = ip1.getWidth(); // var → int
int yy = ip1.getHeight(); // 以下、var を適切に書き換え

libC klib = LibraryLoader.create(libC.class).load("_k_libs");
int zz = klib.Add( 10, 20 );


int x2=xx/2; int y2=yy/2;
ImagePlus imp2 = IJ.createImage( "out", "8-bit", x2, y2, 1 );
ImageProcessor ip2 = imp2.getProcessor();
imp2.show();

for( int y=0; y for( int x=0; x int v = (int)ip1.getf( x, y ); // cast も必須。
ip2.setf( x/2, y/2, zz );
}
}

imp2.updateAndDraw();

// =========================
}
}
以上の様なもの。

それから、
ImageJ インストール場所:D:/TOOL/ImageJ/ に、
4Dir と、「_k_libs.dll」を置き、

上記「k_Java_FFI.java」を
 D:/TOOL/ImageJ/plugins/_kami/ に置いた。



これで、ImageJでのコンパイルは正常?

しかし、実行してみると エラー
  java.lang.NoSuchMethodError: com.kenai.jffi.・・・
メソッドが見つからない???


この時の「Exception.txt」の内容は:
ImageJ 1.50i; Java 1.6.0_20 [32-bit]; Windows 7 6.1; 4295K of 640MB (<1%)

java.lang.NoSuchMethodError: com.kenai.jffi.CallContextCache.getCallContext(Lcom/kenai/jffi/Type;[Lcom/kenai/jffi/Type;Lcom/kenai/jffi/CallingConvention;Z)Lcom/kenai/jffi/CallContext;
at jnr.ffi.provider.jffi.InvokerUtil.getCallContext(InvokerUtil.java:205)
at jnr.ffi.provider.jffi.AsmLibraryLoader.generateInterfaceImpl(AsmLibraryLoader.java:127)
at jnr.ffi.provider.jffi.AsmLibraryLoader.loadLibrary(AsmLibraryLoader.java:59)
at jnr.ffi.provider.jffi.NativeLibraryLoader.loadLibrary(NativeLibraryLoader.java:43)
at jnr.ffi.LibraryLoader.load(LibraryLoader.java:287)
at jnr.ffi.LibraryLoader.load(LibraryLoader.java:266)
at k_Java_FFI.run(k_Java_FFI.java:25)
at ij.IJ.runUserPlugIn(IJ.java:216)
at ij.IJ.runUserPlugIn(IJ.java:229)
at ij.IJ.runPlugIn(IJ.java:180)
at ij.Executer.runCommand(Executer.java:137)
at ij.Executer.run(Executer.java:66)
at java.lang.Thread.run(Thread.java:619)
これでは、

JNR-FFI は、ImageJ プラグイン(Java)では使えない?

アキラメ?


本日はここまで。


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


170329
スポンサーサイト

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

Java 学習:jnr-ffi 導入

2017-04-28 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-04-26)の記事「Java SE 8 導入」で、
Java 開発環境が出来た(?)ので、

「Java FFI」と検索してみたら、・・・・・

今日もプログラミング
jnr-ffiでJavaからCを呼び出す (Windows)」が見つかった。

  jnr-ffiとは?

  JavaからCを呼び出す、と言えばJNIだが、
  C側にJNI固有の処理を書いたりするので結構めんどい。

  jnr-ffiというフレームワークを使うと、
  C側の関数をそのままJavaにマッピングして呼べるらしい。

  具体的には、C側に
int length(char *s)
  のような関数があると、Java側から
int length(String s)
  というほぼそのままのメソッドで呼び出せてしまう!

  という訳で、今回はこのjnr-ffiを実際に試してみる。
  ・・・・・
  ・・・・・

これは!
(<紙>でも)使えるモノなら、使いたい。

これ:jnr/jnr-ffi
ですね。


それで、
  jnr-ffiをダウンロードする
に従って、

 1番目のサイトから「jnr-ffi-2.0.3.jar」
 2番目のサイトから「jffi-1.2.9-native.jar」と「jffi-1.2.9.jar」
 3番目のサイトから「asm-5.0.3-bin.zip」

以上をダウンロードした。

3番目の ZIP 書庫の中には、6つある:
 「asm-5.0.3.jar」、「asm-analysis-5.0.3.jar」、
 「asm-commons-5.0.3.jar」、「asm-tree-5.0.3.jar」、
 「asm-util-5.0.3.jar」、「asm-xml-5.0.3.jar」


それから?

取り敢えず、
上記9つの .jar ファイル名からバージョン番号(ハイフンも)外した。

そして、
jnr/jnr-ffi
Example「helloworld」
をコピペし、コンパイル:
javac  -cp  jnr-ffi.jar  helloworld.java
ここで、“-cp”とは、“--classpath”のコト?

helloworld.class ファイルは出来た。
が・・・・・
実行:
java  helloworld
でアボート?????


さんざん悩んだ挙げ句、・・・・・

9ヶの「~.jar」を解凍して、併合した。

結果、4つのフォルダにまとまった:
「jnr/ffi」 以下6フォルダと183ファイル
「jni」 以下13フォルダ
「com/kenai/jffi」 以下1フォルダと122ファイル
「org/objectweb/asm」 以下5フォルダと22ファイル

これらを、
  C:/_kami_/ に格納し、

classpath に c:/_kami_ を追加した。

ここで、注意することは、カレント Dir の扱い!
  参照:「CLASSPATH

なので、
コンパイルは:
javac  -cp  .;C:/_kami_  hoge.java
とし、
実行は:
java  -cp  .;C:/_kami_  hoge
でも、
上記は上手く行かない???


そこで、
3年前(2014-05-18)の記事「Python 学習:ctypes 入門
で作った「test_dll.dll」を使ってテスト。
// ===== k_testC =====
import jnr.ffi.LibraryLoader; // 全4Dir必要

public class k_testC{ // これはファイル名と同じ

public static interface libC { // これは適切に
int Add( int a, int b ); // 呼出関数のプロトタイプ
}

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

libC klib = LibraryLoader.create(libC.class).load("test_dll");
// 適切に ^^^^^^^^^^^^ 上記 呼出DLL名

int zz = klib.Add( 10, 20 );
// 上記

System.out.print( zz );

}
}
/* コンパイルは:
   javac -cp .;C:/_kami_ k_testC.java
これで、2つの .class が出来る。

実行は:
   java -cp .;C:/_kami_ k_testC

いずれにおいても、4フォルダは必要
実行時には、更に両 class ファイルが必要
*/
これは動いた。

jnr-ffiが使えた。 バンザイ!

でも、何故 本家の Example が動かない???
  LibC libc = LibraryLoader.create(LibC.class).load("c");
.load("c") が問題???


本日はここまで。


Java 学習は続く。


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


170326

Java SE 8 導入

2017-04-26 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
Java については、
昨年10月(2016-10-26)の記事「ImageJ Plugin(Java):WindowManagerクラス
以降、お休みだった。

学習を継続しようと思い、ImageJ内でのコンパイルじゃなくて、
直接、javacコマンドでやりたい。
それには、どうする???

「Java 入門」検索で、
一番かんたんなJava入門
を見つけたので、これを参考にさせて頂いた。

先ずは、
【java】 JDKのダウンロードとpathの設定」ですね。

ここには、
  Java SE - Downloads | Oracle Technology Network | Oracle
  でJDKをダウンロード出来ます。
とあるので、
リンク先に行き、
「jdk-8u121-windows-i586.exe」をダウンロード 189.36 MB
( Java SE 8 の Windows x86 版 )

そして、インストール。 → C:/Program Files (x86)/Java/jdk1.8.0_121/
338MB だった。

パスには登録されないので、追加:
   C:\Program Files (x86)\Java\jdk1.8.0_121\bin
ですか。

これで、コンパイルは: javac hoge.java
    実行は:    java hoge
実行時に、“.class”を付けるとエラーになる???

そして、ソースファイルのコードは:Sift-JIS


作業用フォルダを作り、ここで学習。

試しに、「【Java】コンパイルと実行」の例:
Test.java(5行分)をコピペして、
コンパイル:
  javac Test.java
そして実行:
  java Test

OKダ。

ここで、メインclassの定義が大きく異なる。
上記のサンプルでは:
public  class  Test{
public static void main( String[] args ){
の様だが、
ImageJ Plugin(Java) では、
public  class  test_WindowManager_Java  implements  PlugIn{
public void run( String arg ){
の様にしないとダメ?
つまり、mainrun が異なる。


更に、「Java サンプル」検索で、
JavaDriveの「Java入門」の
サンプルプログラム(電卓)」の「完成版」つまり「dentaku4.java」を頂き、
同様にコンパイル&実行。

これも、OK。


少々、Javaの学習ダ。

本日はここまで。


Java 学習は続く。


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


170325

Python:call_Lua51 似非モジュール

2017-04-24 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
先日(2017-04-19)の記事「SpiderMonkey:call_Lua51 似非モジュール」では、
その前(2017-04-17)の記事「call_Lua 似非モジュール:Lua51 汎用・決定版」を、
SpiderMonkey”に移植してみた。

今回は、同様に“Python”で作ってみた。


なんとか出来ました:
# -*- coding: utf-8 -*-
# ----- call_Lua51_Gen.py -----
import sys
import numpy as np
import ctypes as ct
lua = ct.CDLL( 'lua51' )

# ----- int32_t 配列6要素、値格納
IT = np.array( [1,2,3,4,5,0], dtype=ct.c_int );
# ----- double 5要素
DT = np.array( [1.1, 2.2, 3.3, 4.4, 5.5], dtype=ct.c_double );

IT[5]= ct.cast( id(DT), ct.POINTER(ct.c_int) ) [2]
ST=''' print("Lua5.1---")
ffi.cdef[[ double sqrt(double); ]]
print( ffi.C.sqrt(3.0) )
print( math.sin(1.0) )
require"lfs"; print( lfs.currentdir() )
t=require"time"; print(t.time())
print(IT[2])
DT=DblA(IT[5]); print(DT[3])
IT[0]=999; SV="ok!"
'''

L = lua.luaL_newstate()
lua.luaL_openlibs(L)
z = lua.luaL_loadfilex(L, 'Lua51_Gen.lua', 0)
z = lua.lua_pcall(L, 0, 0, 0 ) # -- script を1度実行

lua.lua_getfield( L, -10002, 'Exec' ); # -- 呼び出す関数
lua.lua_pushinteger( L, IT.ctypes.data_as(ct.POINTER(ct.c_int)) );
lua.lua_pushstring( L, ct.c_char_p(ST) ); # -- 第2引数:Lua5.1 での実行文

if (lua.lua_pcall(L, 2, 1, 0) != 0): # -- 引数 2 個, 戻り値 1 個
print 'cannot exec.', L; # ----- 中で、実行
sys.exit()

if( lua.lua_isstring(L, -1)):
ToStr = lua.lua_tolstring
ToStr.restype = ct.c_char_p
SV = ToStr(L, -1, 0); # -- 戻り値
print( SV ); # -- 'OK'~

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

print( IT[0] )
_=raw_input()
と云った感じ。
コーディング量は少ないかナ。

尚、このプログラムファイルのコードは 'UTF-8' です。

このプログラムと「Lua51_Gen.lua」の他に、
「lua51.dll」「lfs.dll」「time.lua」も一緒に置いておく。


出来た?


本日はここまで。


Lua ( GSL Shell ) 学習は続く。


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


170325

UFO - includes OpenGL and glu, ・・・

2017-04-23 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
改めて「LuaJIT library」と検索して見たら、
List of Available Packages - LuaJIT Wiki
が目に入った。

じっくり見てみたら、
最後に

  Bundles
  ・ UFO - includes OpenGL and glu, OpenCL, SDL, ZeroMQ, GLFW

がある。

リンク先は「malkia/ufo」ですね。

面白そうなので、右にある緑地の“Clone or download”ボタンをクリックして、
Download ZIPリンクからダウンロードしてみた。

 「ufo-master.zip」 2014/03/20 付 53.9MB

ですね。

D:/TOOL/Lua/UFO/ に展開した。
ディレクトリが9つで、ファイルが7つ。 181MB

メインは、luajit.cmd でしょうか?

その場所で起動してみると、バージョン表示では

  LuaJIT 2.1.0-alpha

と出た。

試しなので、そこに /test/ フォルダを作り、
その中に、
  /samples/cairo/ フォルダにある pdf.lua
を、コピーし、
フルパス名指定で、
  luajit.cmd pdf.lua
とすると、
実行出来て、「test.pdf」「test.png」「test.svg」が出来た。

これで、
  gsl-shell pdf.lua
としたら、
いろいろ不足している、エラーになるが、

1. /ffi/ cairo.lua
2. /bin/Windows/x86/ cairo.dll
更に、
2.と同じ場所にある、
bz2.dll、freetype2.dll、pixman.dll、png.dll、regal.dll、z.dll
の6こも持ってくると、使える?


更に試してみると、
LFSは入っていない
・パス(D:\TOOL\Lua\UFO)を登録すれば使える
require'ffi'は必要

と云った処まで分かった。


本日はここまで。


UFO 学習は続く?


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


170321,22

wxLua: dll の利用にはムリがある

2017-04-22 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-04-21)の記事:
call_Lua52 似非モジュール(基本Lua呼び出し)」で書いた如く、
Lua52.dll を利用することで、
基本Luaの呼び出しが出来た。

ここまで頑張ったのは、
昨年7月(2016-07-22)の記事「wxLua って何?」で導入してみた、
“wxLua”を“LuaJIT”から使いたいが為で始めたこと。

基本LuaLuaJITではバイトコードの互換性が無く、
“wxLua”はLua5.2だったから。


ところが、wxLuaにある、Lua52.dll は他に流用出来ない。
謂わばダミー

また、wx.dll も、
wxLua.exe からは使えるが、Lua52.exe からは使えない。

結局、wxLua.exeを起動するしかない。


と云うことは、サブルーティンとして使うことは出来ないと云うこと?


<紙>流では、
以前(2017-04-10)の記事「GSL Shell と Lua で、プロセス間通信
で書いた方式しか使えない???


call_Lua 方式は諦め???


本日はここまで。


Lua ( GSL Shell ) 学習は続く。


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


170317

call_Lua52 似非モジュール(基本Lua呼び出し)

2017-04-21 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
以前(2017-04-14)の記事「call_Lua 似非モジュール」では、
Lua インストール場所にあるlua53.dllを使って、
基本Luaの呼び出しを、ほぼ出来たが最後の最後でアボートした。

それで、
GSL Shell インストール場所にあるlua51.dllを使って、
学習した結果:
前々回(2017-04-17) の記事:
call_Lua 似非モジュール:Lua51 汎用・決定版」の如く、
これは全く正常に出来た。

だが、
この時呼び出したのはLuaJITでした。
そもそもは、基本Luaを呼び出したかった。

そこで、
改めて Lua サイト の、
downloadページに行き
右側中央あたりにある
  Binaries
  If you don't have the time or the inclination to compile Lua yourself,
   get a binary or try the live demo.・・・
リンクをクリックした。

この Lua Binaries
ページの一番下( Notes to ・・・ の上 )
  ・Windows
   See [LuaForge Lua Binaries project] for the most recent versions
    for Windows.
リンク先
の中から、
  [31/Mar/2014]
    ・Lua 5.2.3 - Release 1
     Same configuration as the previous release.
を選んで飛んだ。

そこで、
  「Windows Libraries」→「Dynamic」

つまり、
  「LuaBinaries

の一番上:
  「lua-5.2.3_Win32_dll14_lib.zip」 2015-08-29 付  115.8 kB

をダウンロードした。

この中にある「lua52.dll」 2015-08-29 付 200KB
1つあると良さそう。

だが、この中には、
単独実行したい場合に欲しい「lua.exe」が無い!


そこで、「lua-5.2.3_Win32_bin.zip」と検索してみたら、
真っ先に、「Lua Binaries Download
が見つかる。

この中には lua-5.2.3 は無くて、lua-5.2.4 のみ。

  「lua-5.2.4_Win32_bin.zip」 Windows x86 Executables

を選んでダウンロードした。 267KB

この ZIP の中に、
  「lua52.exe」「lua52.dll」等がある。
   全て 2015-12-14 付

この2つがあれば、基本Lua( Ver. 5.2 ) が使える。


そこで、
call_Lua 似非モジュール:Lua51 汎用・決定版
の「call_Lua51_Gen.gsl」を書き直してみた。


Lua51(JIT)  → Lua52(基本)
----------------------------
lua_pcall  → lua_pcallk
lua_getfield → lua_getglobal

以上の2つの関数を変更して完成した:
----- call_Lua52_Gen.gsl -----
ffi=require'ffi'
---------------------- init_After --------------
F=io.open(arg[0]); w=F:read('*a'); F:close(); fnd=string.find
m='--ini'; _,k=fnd(w,m..'s',1,true); j=fnd(w,m..'e',k,true)
assert(load( string.sub(w,k+2,j-1) ))()
----------- 以下部分が本体 ---------------------
----- 以下 Lua5.2 で実行したいコード群
ST=[[ print('Lua5.2---')
print( 2+5 )
print( os.time() )
SV='ok!'
print( _VERSION)
]]
---------------------- インタフェースデータ
IT=ffi.new('int32_t[6]',1,2,3,4,5,0)
----------------------------

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

z = lua.luaL_loadfilex(L, 'Lua52_Gen.lua', 'bt' )
z = lua.lua_pcallk(L, 0, 0, 0, 0, NULL );

lua.lua_getglobal(L, 'Exec' ); -- 呼び出す関数

lua.lua_pushinteger( L, Int32(voidA(IT)) ) -- 第1引数:lua_Integer

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

if (lua.lua_pcallk(L, 2, 1, 0, 0, NULL) ~= 0) then -- 引数 2 個, 戻り値 1 個
printf( nil, 'cannot exec. %s\n', tostring(L)); ----- 中で、実行
os.exit(0)
end
if( lua.lua_isstring(L, -1)) then
SV = lua.lua_tolstring(L, -1, voidA(0)); -- 戻り値
print( ffi.string(SV) ); -- 'OK'~
end
lua.lua_settop(L, -2); -- lua_pop(L,1); 戻り値を pop
lua.lua_close(L)

print( IT[0] )

---------- 以下初期化部分
os.exit(0) ----- これ必須 次の行の1行下の行頭から 初期化部分
--inis
lua = ffi.load( 'lua52' )
ffi.cdef[[ typedef void L_S;
typedef double lua_Number; typedef int32_t lua_Integer;
L_S* luaL_newstate( void );
void luaL_openlibs( L_S* L );

int luaL_loadfilex( L_S* L, const char* filename, const char* mode);
int lua_pcallk( L_S* L, int nargs, int nresults, int errfunc, int ctx, void* k );

void lua_getglobal( L_S* L, const char* name );
void lua_pushinteger(L_S* L, lua_Integer n);
char* lua_pushstring( L_S* L, const char* s);

int lua_isstring( L_S* L, int index );
char* lua_tolstring( L_S* L, int index, size_t* len );
void lua_settop( L_S* L, int m ); // m == -(n) - 1
void lua_close( L_S* L );
]]
Int32 = |s| ffi.cast( 'int32_t', s )
voidA = |s| ffi.cast( 'void*', s )
function printf( f, s, ... )
f = f or io.stdout
f:write(s:format(...))
end
--inie この行の1行上の行末まで



それで、呼び出す Lua52_Gen.lua は:
----- Lua52_Gen.lua -----
function Exec( IT_, ST_ )
IT=IT_; SV='OK'
assert( load( ST_ ) )()
return SV
end
でしょうか。


これで、基本Luaの呼び出しも出来た。


本日はここまで。


Lua ( GSL Shell ) 学習は続く。


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


170317

SpiderMonkey:call_Lua51 似非モジュール

2017-04-19 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-04-17)の記事「call_Lua 似非モジュール:Lua51 汎用・決定版」で、
call_Lua51_Gen.gsl から、Lua51_Gen.lua を呼び出せたが、
所詮 GSL Shell からの LuaJIT の呼び出しで、全く無意味なこと?


そこで、本当の? call_Lua と云うことで、
他言語から、Lua を呼ぶことに挑戦。

とは云っても、似非モジュールなので、

ctypes を持っている Python
か、
js-ctypes を持っている SpiderMonkey
で無いとダメ。

先ずは、
JavaScript(SpiderMonkey) から、LuaJIT を呼ぶことにした。

これ即ち、call_Lua51_Gen.gslSpiderMonkey に移植すること?


なんとか出来ました:
// ----- call_Lua51_Gen.js -----
var VOID = ctypes.void_t; var VoidA = ctypes.voidptr_t;
var Char = ctypes.char; var CharA = Char.ptr
var Int32 = ctypes.int32_t;
var WinABI = ctypes.winapi_abi;
var Cast = ctypes.cast; var Dbl = ctypes.double;
var lib = ctypes.open( 'lua51' );

var L_S = VoidA; var lua_Int = Int32; var SZ_t = ctypes.size_t;

var luaL_newstate = lib.declare( 'luaL_newstate', WinABI, L_S );
var luaL_openlibs = lib.declare( 'luaL_openlibs', WinABI, VOID, L_S );
var luaL_loadfilex= lib.declare( 'luaL_loadfilex', WinABI, Int32, L_S, CharA, CharA );
var lua_pcall = lib.declare( 'lua_pcall', WinABI, Int32, L_S, Int32, Int32, Int32 );
var lua_getfield = lib.declare( 'lua_getfield', WinABI, VOID, L_S, Int32, CharA );

var lua_pushinteger=lib.declare( 'lua_pushinteger',WinABI, VOID, L_S, lua_Int );
var lua_pushstring= lib.declare( 'lua_pushstring', WinABI, CharA, L_S, CharA );
var lua_isnumber = lib.declare( 'lua_isnumber', WinABI, Int32, L_S, Int32 );
var lua_isstring = lib.declare( 'lua_isstring', WinABI, Int32, L_S, Int32 );
var lua_tointeger = lib.declare( 'lua_tointeger', WinABI, lua_Int, L_S, Int32 );
var lua_tolstring = lib.declare( 'lua_tolstring', WinABI, CharA, L_S, Int32, SZ_t );

var lua_gettop = lib.declare( 'lua_gettop', WinABI, Int32, L_S );
var lua_type = lib.declare( 'lua_type', WinABI, Int32, L_S, Int32 );
var lua_settop = lib.declare( 'lua_settop', WinABI, VOID, L_S, Int32 );
var lua_close = lib.declare( 'lua_close', WinABI, VOID, L_S );

//-------------------------------
// 以下 Lua5.1 で実行したいコード
ST=' print("Lua5.1---")'+
'ffi.cdef[[ double sqrt(double); ]]'+
'print( ffi.C.sqrt(3.0) )'+
'print( math.sin(1.0) )'+
'require"lfs"; print( lfs.currentdir() )'+
't=require"time"; print(t.time())'+
'print(IT[2])'+
'DT=DblA(IT[5]); print(DT[3])'+
'IT[0]=999; SV="ok!"'
//-------------- インタフェースデータ
var DT = Dbl.array(5)( [1.1, 2.2, 3.3, 4.4, 5.5] );
var IT = Int32.array(6)( [1,2,3,4,5,0] );
IT[5] = Cast( DT.address(), Int32 );
//--------------

L = luaL_newstate();
luaL_openlibs(L);

z = luaL_loadfilex(L, 'Lua51_Gen.lua', 'bt');
z = lua_pcall(L, 0, 0, 0 ); // script を一度実行しておく

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


lua_pushinteger( L, Cast(IT.address(),Int32) ); // 第1引数:lua_Integer

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

if (lua_pcall(L, 2, 1, 0) != 0) { // 引数 2 個, 戻り値 1 個
print( 'cannot exec.' ); //// 中で、実行 ---------
}
if( lua_isstring(L, -1)) {
SV = lua_tolstring(L, -1, 0); // 戻り値
print( SV.readString() ); // 'OK'~
}
lua_settop(L, -2); // lua_pop(L,1); 戻り値を pop
lua_close(L)

print( IT[0] )
となった。
尚、このプログラムファイルのコードは 'UTF-8' です。

このプログラムと「Lua51_Gen.lua」の他に、
「lua51.dll」「lfs.dll」「time.lua」も一緒に置いておく。


出来たようダ


SpiderMonkey ( JavaScript/js-ctypes ) 学習は続く。


本日はここまで。


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


170316

call_Lua 似非モジュール:Lua51 汎用・決定版

2017-04-17 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-04-16)の記事「call_Lua 似非モジュール:Lua プログラム汎用化」で、
汎用的なものが作れる目処が立った。

そこで、
再設計を行った。
但し、汎用・決定版と云っても、
所詮 GSL Shell からの LuaJIT の呼び出しで、全く無意味なこと?


さて、今回参考にしたのは、
2月(2017-02-17)の記事「LuaPy_GSL モジュール化」で書いた、
SUB_LuaPy_GSL_Gen.pyに相当するもの。

Lua では、戻り値を文字列に出来たので、

関数名を Exec として、
引数は2つ、戻り値は文字列。


2つの引数について:

第1(IT):整数(int)型データの配列
第2(ST):実行したい Lua ソーステキスト文字列データ

そして、SUB_LuaPy_GSL_Gen.py では、
ST の文字列長を IT[0] で指定していたが、
これは特段指定しなくても出来る。

と云うことで、Lua51_Gen.lua は:
----- Lua51_Gen.lua -----
ffi = require'ffi'
function voidA(s) return ffi.cast( 'void*', s ) end
function IntA(s) return ffi.cast( 'int32_t*', s ) end
function DblA(s) return ffi.cast( 'double*', s ) end
function Exec( IT_, ST_ )
IT=IntA(IT_); SV='OK'
assert( load( ST_ ) )()
return SV
end
でしょうか。
最初の require'ffi' と、
続く function 3つは、汎用で定義しておく。


それで、テスト用 call_Lua51_Gen.gsl は:
以前(2017-04-12)の記事「GSL Shell 学習:見た目の前方参照?(新方式)
で書いた方式で作ってみた。
----- call_Lua51_Gen.gsl -----
ffi=require'ffi'
---------------------- init_After -----------------
F=io.open(arg[0]); w=F:read('*a'); F:close(); fnd=string.find
m='--ini'; _,k=fnd(w,m..'s',1,true); j=fnd(w,m..'e',k,true)
assert(load( string.sub(w,k+2,j-1) ))()
----------- 以下部分が本体 ------------------------
----- 以下 Lua5.1 で実行したいコード群
ss1=[[ print('Lua5.1---')
ffi.cdef[[ int rand(void);
double sqrt(double); ]]
ss2=[[
print( ffi.C.sqrt(3.0) )
print( math.sin(1.0) )
require'lfs'; print( lfs.currentdir() )
t=require'time'; print(t.time())
print(IT[2])
DT=DblA(IT[5]); print(DT[3])
IT[0]=999; SV='ok!'
]]
ST=ss1..']]'..ss2 -- 上記2つの文字列結合
----------------- インタフェースデータ
DT=ffi.new('double[5]', 1.1, 2.2, 3.3, 4.4, 5.5 )
IT=ffi.new('int32_t[6]',1,2,3,4,5,0)
IT[5]=Int32(voidA(DT))
-----------------

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

z = lua.luaL_loadfilex(L, 'Lua51_Gen.lua', 'bt' )
z = lua.lua_pcall(L, 0, 0, 0 ); -- script を一度実行しておく

lua.lua_getfield( L, -10002, 'Exec' ) -- 呼び出す関数
----- -10002 == LUA_GLOBALSINDEX

lua.lua_pushinteger( L, Int32(voidA(IT)) ) -- 第1引数:lua_Integer

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

if (lua.lua_pcall(L, 2, 1, 0) ~= 0) then -- 引数 2 個, 戻り値 1 個
printf( nil, 'cannot exec. %s\n', tostring(L)); ----- 中で、実行
os.exit(0)
end
if( lua.lua_isstring(L, -1)) then
SV = lua.lua_tolstring(L, -1, voidA(0)); -- 戻り値
print( ffi.string(SV) ); -- 'OK'~
end
lua.lua_settop(L, -2); -- lua_pop(L,1); 戻り値を pop
lua.lua_close(L)

print( IT[0] )

---------- 以下初期化部分
os.exit(0) ----- これ必須 次の行の1行下の行頭から 初期化部分
--inis
lua = ffi.load( 'lua51' )
ffi.cdef[[ typedef void L_S;
typedef double lua_Number; typedef int32_t lua_Integer;
L_S* luaL_newstate( void );
void luaL_openlibs( L_S* L );

int luaL_loadfilex( L_S* L, const char* filename, const char* mode);
int lua_pcall( L_S* L, int nargs, int nresults, int msgh );

void lua_getfield( L_S* L, int i , const char* name );
void lua_pushinteger(L_S* L, lua_Integer n);
char* lua_pushstring( L_S* L, const char* s);

int lua_isstring( L_S* L, int index );
char* lua_tolstring( L_S* L, int index, size_t* len );
void lua_settop( L_S* L, int m ); // m == -(n) - 1
void lua_close( L_S* L );
]]
Int32 = |s| ffi.cast( 'int32_t', s )
voidA = |s| ffi.cast( 'void*', s )
function printf( f, s, ... )
f = f or io.stdout
f:write(s:format(...))
end
--inie この行の1行上の行末まで
で行ける?

なお、以上の2本のプログラムの他に、
「lua51.dll」「lfs.dll」「time.lua」も一緒に置いておく。


出来たようダ


本日はここまで。


Lua ( GSL Shell ) 学習は続く。


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


170315

call_Lua 似非モジュール:Lua プログラム汎用化

2017-04-16 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-04-15)の記事「call_Lua 似非モジュール:Lua51.dll 利用版」で、
GSL Shell インストール場所にあるLua51.dllを使った。

今回は、
呼び出す Lua 関数を汎用的なものとした。
その為には、文字列データの受け渡しをどうするか?

これまでの参考資料を、更に学習し出来た様ダ。


先ず、呼び出す Lua プログラムは:
----- fun_eval.lua -----
function EVAL( arg1 )
assert( load( arg1 ) )()
return 'OK'
end
と、
引数1つで文字列と想定。
戻り値も1つで、文字列。

これを利用する、GSL Shell プログラム ( = call_Lua 似非モジュール ):
----- call_Lua_Gen.gsl -----
lua = ffi.load( 'lua51' )
ffi.cdef[[ typedef void L_S;
typedef double lua_Number; typedef int32_t lua_Integer;
L_S* luaL_newstate( void );
int lua_gettop( L_S* L );
int lua_type( L_S* L, int index );
void luaL_openlibs( L_S* L );

int luaL_loadfilex( L_S* L, const char* filename, const char* mode);
int lua_pcall( L_S* L, int nargs, int nresults, int msgh );
void lua_getglobal( L_S* L, const char* name );

void lua_getfield( L_S* L, int i , const char* name );
void lua_pushnumber( L_S* L, lua_Number n );
char* lua_pushstring( L_S* L, const char* s);

int lua_isstring( L_S* L, int index );
int lua_isnumber( L_S* L, int index );
lua_Integer lua_tointeger( L_S* L, int idx );
// char* lua_tostring( L_S* L, int index ); // これは無し?
char* lua_tolstring( L_S* L, int index, size_t* len );
void lua_settop( L_S* L, int m ); // m == -(n) - 1
void lua_close( L_S* L );
]]
charA = |s| ffi.cast( 'char*', s )
voidA = |s| ffi.cast( 'void*', s ); NULL=voidA(0)
function printf( f, s, ... )
f = f or io.stdout
f:write(s:format(...))
end
---------------------------------------
----- Lua5.1 で実行したいコード群
sss=[[ print( 'Lua5.1---' )
print( math.sin(1) )
t=require'time'; print( t.time() )
]]
---------------------------------------

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

z = lua.luaL_loadfilex(L, 'fun_eval.lua', charA(0))
z = lua.lua_pcall(L, 0, 0, 0 ); -- script を1度実行

lua.lua_getfield( L, -10002, 'EVAL' ); -- 呼び出す関数

lua.lua_pushstring(L, sss ); -- 引数:Lua5.1 での実行コード

if (lua.lua_pcall(L, 1, 1, 0) ~= 0) then -- 引数 1 個, 戻り値 1 個
printf( nil, 'cannot exec. %s\n', tostring(L)); ----- 中で、実行
os.exit(0)
end
if( lua.lua_isstring(L, -1)) then
ret = lua.lua_tolstring(L, -1, NULL); -- 戻り値
print( ffi.string(ret) ); -- 'OK'
end
lua.lua_settop(L, -2); -- lua_pop(L,1); 戻り値を pop
lua.lua_close(L)
これで、
取り敢えず、文字列 sss を実行する事ができる。


ここで、
いろいろ試行錯誤していて、・・・・・

このlua51.dllを使うと、
LuaJIT で使えるFFIが使える事が分かった。

つまり、
上記の文字列 sss を、例えば:
ss1 = [[   print('Lua5.1---')
ffi = require'ffi'
ffi.cdef[[ int rand(void);
double sqrt(double);
]]

ss2 = [[
print( ffi.C.rand() ) -- 乱数生成
print( ffi.C.rand() ) -- 乱数生成
print( ffi.C.sqrt(3.0) ) -- 平方根算出
require'lfs'; print( lfs.currentdir() )
t=require'time'; print(t.time())
]]

sss = ss1..']]'..ss2
の様なものにすることも出来た。


本日はここまで。


call_Lua 似非モジュール 学習は続く。


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


170314

call_Lua 似非モジュール:Lua51.dll 利用版

2017-04-15 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-04-14)の記事「call_Lua 似非モジュール」では、
Lua インストール場所にあるLua53.dllを使た。
しかし、
  ・・・・・
  ・・・・・
  一応処理結果は正しそうだが、
  最終的に「libgcc_s_dw2-1.dll」が無い でアボート???
  ・・・・・
  ・・・・・
で、
精神衛生上ヨロシク無い。


それでは、
と、
GSL Shell インストール場所にあるlua51.dllを使ったらどうか?


今回更なる参考資料として、
サイト:「Lua 5.1 リファレンスマニュアル
へのショートカットと、
ヘッダファイル「lua51.h」を参照。
これは、定数の定義値を参照するため。


単純に、
前回の最初の文:
  lua = ffi.load( 'lua53' )

  lua = ffi.load( 'lua51' )
に変えたダケではエラー!?!?!?

いろいろ変更して、
出来上がったコードは:
----- test_call_Lua51.gsl -----
lua = ffi.load( 'lua51' )
ffi.cdef[[ typedef void L_S;
typedef double lua_Number; typedef int32_t lua_Integer;
L_S* luaL_newstate( void );
int lua_gettop( L_S* L );
int lua_type( L_S* L, int index );
void luaL_openlibs( L_S* L );
// int luaL_loadfile( L_S* L, const char* filename); // これは無し***
int luaL_loadfilex( L_S* L, const char* filename, const char* mode);
int lua_pcall( L_S* L, int nargs, int nresults, int msgh );
// int lua_pcallk( L_S* L, int nargs, int nresults, int errfunc, int ctx, void* k );
// void lua_getglobal( L_S* L, const char* name ); // これは無し***
// void lua_getfield( L_S* L, LUA_GLOBALSINDEX, const char* name );
void lua_getfield( L_S* L, int i , const char* name );
void lua_pushnumber( L_S* L, lua_Number n );
int lua_isnumber( L_S* L, int index );
lua_Integer lua_tointeger( L_S* L, int index );
// lua_Integer lua_tointegerx( L_S* L, int index, void* isnum );
void lua_settop( L_S* L, int m ); // m == -(n) - 1
void lua_close( L_S* L );
]]
charA = |s| ffi.cast( 'char*', s )
voidA = |s| ffi.cast( 'void*', s ); NULL=voidA(0)
function printf( f, s, ... )
f = f or io.stdout
f:write(s:format(...))
end
----- 以下 print は、デバッグ用
L = lua.luaL_newstate(); print( L ); --
lua.luaL_openlibs(L)

z = lua.luaL_loadfilex(L, 'func.lua', charA(0)); -- 呼び出すProg
print(z) -- 0
S = lua.lua_gettop(L); T = lua.lua_type(L, 1); print( S, T ) -- 1 , 6

z = lua.lua_pcall(L, 0, 0, 0 ); -- script を実行しておかないと関数を呼び出せない
print(z) -- 0

-- lua.lua_getglobal(L, 'fun' ); -- 呼び出す関数
lua.lua_getfield( L, -10002, 'fun' ); -- 呼び出す関数
S = lua.lua_gettop(L); T = lua.lua_type(L, S); print( S, T ) -- 1, 6

lua.lua_pushnumber(L, 4); -- 第一引数
S = lua.lua_gettop(L); T = lua.lua_type(L, S); print( S, T ) -- 2, 3

lua.lua_pushnumber(L, 5); -- 第ニ引数
S = lua.lua_gettop(L); T = lua.lua_type(L, S); print( S, T ) -- 3, 3

if (lua.lua_pcall(L, 2, 2, 0) ~= 0) then -- 引数 2 個, 戻り値 2 個
printf( nil, 'cannot exec add. %s\n', tostring(L)); ----- 中で、4.0 5.0 を print
os.exit(0)
end
if( lua.lua_isnumber(L, -1)) then
ret = lua.lua_tointeger(L, -1); -- 戻り値その 1
printf( nil, "ret=%d\n", ret); -- 7 == 5 + 2
end
S = lua.lua_gettop(L); lua.lua_settop(L, S-1); -- lua.lua_pop(L,1); 戻り値を pop
if (lua.lua_isnumber(L, -1)) then
ret = lua.lua_tointeger(L, -1); -- 戻り値その 2
printf( nil, "ret=%d\n", ret); -- 5 == 4 + 1
end
S = lua.lua_gettop(L); lua.lua_settop(L, S-1); -- lua.lua.pop(L,1); 戻り値を pop

lua.lua_close(L)
こうなった。


処理結果は、
アボートも起こらず終了。
正しそうだが?


これでも、
関数名が異なっていたり、無かったり、

かなり苦労した。

でも何とか完成した?


本日はここまで。


call_Lua 似非モジュール 学習は続く。


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


170313

call_Lua 似非モジュール

2017-04-14 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
先日(2017-04-10)の記事「GSL Shell と Lua で、プロセス間通信」では、
PIPE 2本を使って、EVENT は使わない方式の
プロセス間通信方式を確立した???

でも、やはり Lua を C言語等から直接利用したい。

つまり、
Lua から Python を呼び出す「LuaPy モジュール」の様なモノ


それには、どうすれば良いか???

検索して見たら、
Qiita の「C と lua の連携方法メモ
が見つかった。
  ・・・・・
  ・・・・・
  C から lua の関数呼び出し
  下記の lua 関数を C から呼び出す.
----- func.lua
function func(arg1, arg2)
print(arg1)
print(arg2)
return arg1+1, arg2+2
end
上記を呼び出す C のコード
//=== call.cpp
lua_State* l = luaL_newstate();
luaL_openlibs(l);
luaL_loadfile(l, "func.lua");
lua_pcall(l, 0, 0, 0); // script を実行しておかないと関数を呼び出せない
lua_getglobal(l, "func"); // 呼び出す関数
lua_pushnumber(l, 4); // 第一引数
lua_pushnumber(l, 5); // 第ニ引数
if (lua_pcall(l, 2, 2, 0)) { // 引数 2 個, 戻り値 2 個
fprintf(stderr, "cannot exec add. %s\n", lua_tostring(l, -1));
return;
}
if (lua_isnumber(l, -1)) {
int ret = lua_tointeger(l, -1); // 戻り値その 1
printf("ret=%d\n", ret);
}
lua_pop(l, 1); // 戻り値を pop
if (lua_isnumber(l, -1)) {
int ret = lua_tointeger(l, -1); // 戻り値その 2
printf("ret=%d\n", ret);
}
lua_pop(l, 1); // 戻り値を pop
  ・・・・・
  ・・・・・

正に、この様なことをやりたい。


そこで、参考資料を集めた。


上記検索で見つけたサイト:第6章 C言語との連携

いつも参照している:Lua 5.2 リファレンスマニュアル

Lua5.1 教科書?:Programming in Lua (first edition)

他に検索で見つけた:Lua処理系コード読み(13) luaL_newstate


以上、合計5件を学習した。


ここで、
C言語でコーディングしてコンパイル
はしたくない。

GSL Shell なら、同等な事ができるはず?
それには、何かDLLが必要。


ふと思いついた、
GSL Shell インストール場所にあるlua51.dllでは?

中を見ると、luaL_newstateが有りそう?

そうすると、
Lua インストール場所にあるlua53.dllで行けそう。

と云うことで、上記call.cpp相当を作ってみた。
初めてなので、確認用にかなり print 文を入れている:
----- test_call_lua.gsl -----
lua = ffi.load( 'lua53' )
ffi.cdef[[ typedef void L_S;
typedef double lua_Number; typedef int32_t lua_Integer;
L_S* luaL_newstate( void );
int lua_gettop( L_S* L );
int lua_type( L_S* L, int index );
void luaL_openlibs( L_S* L );
// int luaL_loadfile( L_S* L, const char* filename); // これは無し***
int luaL_loadfilex( L_S* L, const char* filename, const char* mode);
// int lua_pcall( L_S* L, int nargs, int nresults, int msgh ); // これは無し***
int lua_pcallk( L_S* L, int nargs, int nresults, int errfunc, int ctx, void* k );
////////// 正しくは、・・・・・・・・・・・・・・・・・・ int ctx, lua_CFunc k );
void lua_getglobal( L_S* L, const char* name );
void lua_pushnumber( L_S* L, lua_Number n );
int lua_isnumber( L_S* L, int index );
// lua_Integer lua_tointeger( L_S* L, int index ); // これは無し***
lua_Integer lua_tointegerx( L_S* L, int index, void* isnum );
//// void lua_pop( L_S* L, int n ); // これはマクロ***
void lua_settop( L_S* L, int m ); // m == -(n) - 1
void lua_close( L_S* L );
]]
charA = |s| ffi.cast( 'char*', s )
voidA = |s| ffi.cast( 'void*', s ); NULL=voidA(0)
function printf( f, s, ... )
f = f or io.stdout
f:write(s:format(...))
end
----- 以下 print は、デバッグ用
L = lua.luaL_newstate(); print( L ); --
lua.luaL_openlibs(L)

z = lua.luaL_loadfilex(L, 'func.lua', charA(0)); -- 呼び出すProg
print(z) -- 0
S = lua.lua_gettop(L); T = lua.lua_type(L, 1); print( S, T ) -- 1 , 6

z = lua.lua_pcallk(L, 0, 0, 0, 0, NULL); -- script を一度実行しておく
print(z) -- 0

lua.lua_getglobal(L, 'fun' ); -- 呼び出す関数
S = lua.lua_gettop(L); T = lua.lua_type(L, S); print( S, T ) -- 1, 6

lua.lua_pushnumber(L, 4); -- 第一引数
S = lua.lua_gettop(L); T = lua.lua_type(L, S); print( S, T ) -- 2, 3

lua.lua_pushnumber(L, 5); -- 第ニ引数
S = lua.lua_gettop(L); T = lua.lua_type(L, S); print( S, T ) -- 3, 3

if (lua.lua_pcallk(L, 2, 2, 0, 0, NULL) ~= 0) then -- 引数 2 個, 戻り値 2 個
printf( nil, 'cannot exec add. %s\n', tostring(L)); ----- 中で、4.0 5.0 を print
os.exit(0)
end
if( lua.lua_isnumber(L, -1)) then
ret = lua.lua_tointegerx(L, -1, NULL); -- 戻り値その 1
printf( nil, "ret=%d\n", ret); -- 7 == 5 + 2
end
S = lua.lua_gettop(L); lua.lua_settop(L, S-1); -- lua_pop(L,1); 戻り値を pop
if (lua.lua_isnumber(L, -1)) then
ret = lua.lua_tointegerx(L, -1, NULL); -- 戻り値その 2
printf( nil, "ret=%d\n", ret); -- 5 == 4 + 1
end
S = lua.lua_gettop(L); lua.lua_settop(L, S-1); -- lua.pop(L,1); 戻り値を pop

lua.lua_close(L)
これで?

一応処理結果は正しそうだが、
最終的に「libgcc_s_dw2-1.dll」が無い でアボート???


正直に C言語でコーディングしてコンパイルするのでは無いので、・・・・・

マクロであったり、関数名が異なっていたり、

かなり苦労した。

でも何とか行けそうダ。


本日はここまで。


call_Lua 似非モジュールは作れそう。


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


170312

GSL Shell 学習:見た目の前方参照?(新方式)

2017-04-12 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
見た目の前方参照を実現するには、
最初に思いつくのは、goto文があれば、それを利用する方式。

確かに、
昨年2月(2016-02-19)の記事「GSL Shell 学習:gotoで見た目の前方参照」で書いている。
だが、当該記事でも書いた通り“local”宣言がジャマをする。


Python に関しては、“Python 見た目の前方参照”の通り。

つまり、
goto文が無い言語でも、for と if を使えば出来る。


今回、変なことを考えついた。

それは、
1) 自分自身を読み込んで、
2) 後段部分を抜き出し、
3) その文字列を“eval 関数”相当で実行する。


1) については、起動時の引数テーブルで入手できる:
昨年3月(2016-03-06)の記事「GSL Shell 学習:グローバル・テーブル arg
の如く、arg[0] で。

3) については、assert( load( ~ ) )() で出来る:
昨年1月(2016-01-27)の記事「Lua 学習:eval 関数」参照


2) については、
対象範囲を、「--inis」だけの行と「--inie」だけの行の間の行と考えた。
それで、

最初は:
F=io.open(arg[0]); w=F:read('*a'); F:close(); fnd=string.find
_,k=fnd(w,'--inis',1,true); j=fnd(w,'--inie',k,true)
assert(load( string.sub(w,k+2,j-2) ))()
としてみたが、ダメです。
つまり、2行目の判定文にある文字列がジャマをする。

それを解消するため:
F=io.open(arg[0]); w=F:read('*a'); F:close(); fnd=string.find; k=1
for i=1,2 do _,k=fnd(w,'--inis',k,true) end j=fnd(w,'--inie',k,true)
assert(load( string.sub(w,k+2,j-2) ))()
とした。
これで、一応出来た。

しかし、イマイチ気に入らない。

そこで、2行目の判定文がジャマしない様に変えた:
F=io.open(arg[0]); w=F:read('*a'); F:close(); fnd=string.find
m='--ini'; _,k=fnd(w,m..'s',1,true); j=fnd(w,m..'e',k,true)
assert(load( string.sub(w,k+2,j-1) ))()
これで完成。

なお、“fnd=string.find”の第4パラメータは、
“-”が特別な文字とは見なさない為に必要ですネ。


この方式で作ったテストプログラム:
昨年2月(2016-02-05)の記事「GSL Shell 学習:LFS 自作始め
のコード見直しを兼ねて、自ファイルのサイズ取得の例
---- test_init_After.gsl -----
F=io.open(arg[0]); w=F:read('*a'); F:close(); fnd=string.find
m='--ini'; _,k=fnd(w,m..'s',1,true); j=fnd(w,m..'e',k,true)
assert(load( string.sub(w,k+2,j-1) ))()
----------- 以下部分が本体 --------------------
print( string.sub(w,k+2,j-1) ) -- 改行コードは1バイト分

print( f(5) ) -- 10

stat = ffi.new( 'uint32_t[64]' )
_ = ffi.C._stat( arg[0], stat )
print( stat[5] ) -- このファイルのサイズ

----------- 以下初期化部分 --------------------
os.exit(0) ----- これは必須
--inis
function f(x)
return x+5
end
ffi.cdef[[
int _stat ( const char* fname, void* buf );
]]
--inie
------- 以下は 自由領域:主にコメント用 -------

-- コメント

こんな感じ?


本日はここまで。


Lua ( GSL Shell ) 学習は続く。


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


170310,11

GSL Shell と Lua で、プロセス間通信

2017-04-10 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
これまでで、“Lua PIPE”の如く、
数件記事にしている。

今回、
GSL Shell(LuaJIT) と、基本Luaとの間で通信出来るか?
について学習した。

基本的には、
1月(2017-01-25)の記事「クライアント/サーバ:プロセス間通信・改
にある:
  ・・・・・
  ・・・・・
  サーバー側 は前回の“test_Server.gsl”

  クライアント側 は今回の“test_Client_lua.gsl”
  ・・・・・
  ・・・・・

の様なもの。

但し、
一方向での送受信では無く、お互いが送受信するもの。


いろいろ試してみたが、・・・・・


結論としては、

PIPE 1本での双方向はムリ。
なので、
PIPE 2本を使って、それぞれ一方向とした。
これで、
EVENT はイラナイ?


GSL Shell 側で2本の PIPE を“CreateNamedPipeA”しておく。

Lua 側は、2本とも、単なるファイルと思って処理する。
但し、読み込みは“バイト数指定”方式のみ可。


それで、先に起動するもの ( GSL Shell で起動 )
----- test_Server_2Ps.gsl -----
charA = |s| ffi.cast( 'char*', s )
ffi.cdef[[ typedef unsigned int DWORD;
int CreateNamedPipeA( char*, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, int );
int ConnectNamedPipe( int, int );

int ReadFile( int, char*, DWORD, void*, int );
int WriteFile( int, char*, DWORD, void*, int );

int FlushFileBuffers( int hFile );
int DisconnectNamedPipe( int hNamedPipe );
int CloseHandle( int hObject );
]]
----- パイプを作成
P2 = ffi.C.CreateNamedPipeA( charA("\\\\.\\pipe\\pipe2"), 3, 0, 1, 0, 0, 100, 0 )
P1 = ffi.C.CreateNamedPipeA( charA("\\\\.\\pipe\\pipe1"), 3, 0, 1, 0, 0, 100, 0 )
----- Client オープン待ち
rcd = ffi.C.ConnectNamedPipe( P1, 0 )

Buf=ffi.new('char[256]')
nRd=ffi.new('uint32_t[1]'); nWt=ffi.new('uint32_t[1]')

while true do
rcd=ffi.C.ReadFile( P1, Buf, 256, nRd, 0)
str = ffi.string(Buf,nRd[0])
print( str )
sss = string.format('%4d%sHOGE', nRd[0]+4, str )
rcd=ffi.C.WriteFile( P2, charA(sss), nRd[0]+8, nWt, 0 )
if( str == '_e' ) then break end
end
----- 後処理
ffi.C.FlushFileBuffers( P1 ); ffi.C.DisconnectNamedPipe( P1 ); ffi.C.CloseHandle( P1 )
ffi.C.FlushFileBuffers( P2 ); ffi.C.DisconnectNamedPipe( P2 ); ffi.C.CloseHandle( P2 )
の様なもの。
そして、後から起動するもの( 基本 Lua で起動 )
----- test_Client_2Ps.lua

P2 = io.open( '\\\\.\\pipe\\pipe2', 'w+' )
print( P2 ) --------- デバッグ用
P1 = io.open( '\\\\.\\pipe\\pipe1', 'w+' )
print( P1 ) --------- デバッグ用
-------------------------
Buf='hogehoge'
P1:write( Buf ); P1:flush()

n = P2:read( 4 ) + 0
s = P2:read( n )
print( s )
-------------------------
P1:write( 'kamizzz' ); P1:flush()

n = P2:read( 4 ) + 0
s = P2:read( n )
print( s )
-------------------------
P1:write( '_e' ); P1:flush()

P1:close(); P2:close()
となった。

ここで、
Lua 側は、読み込みバイト数を指定しての read で無いとダメ。
なので、
書き出す GSL Shell 側では、先頭4バイトでデータ長を指定している。

また、
Lua 側での書き込み後は、flush が無いとダメ。


本日はここまで。


Lua ( GSL Shell ) 学習は続く。


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


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