Python & tcc 学習:libtcc 直接使用

2017-05-24 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
先日(2017-05-19)の記事「tcc 学習:libtcc 直接使用(成功)」では、

  ・・・・・
  ・・・・・
  つまり、
  カレントには、(正しい?)use_libtcc_inline_C.gsl ダケで十分。

  結局、以下のコードで十分:
  ・・・・・
  ・・・・・

と云うことで、
libtcc.dll”を直に使うだけで、
所謂インラインCコードが使えた。


なので、
今回は Python での“libtcc 直接使用”に挑戦。


先日の“use_libtcc_inline_C.gsl”の移植と云うこと?

出来たコードは:
# -*- coding: utf-8 -*-
# ---------- use_libtcc.py -----
import ctypes as ct
tcc = ct.CDLL( 'libtcc' )

ST=''' int Add( int x, int y ){
return x + y;
}
'''
relocate_auto = ct.c_void_p(1)

TCL = tcc.tcc_new();
z = tcc.tcc_set_output_type( TCL, 0 );

z = tcc.tcc_compile_string( TCL, ST );
tcc.tcc_relocate( TCL, relocate_auto )

Add_proto = ct.CFUNCTYPE( ct.c_int, ct.c_int, ct.c_int )
Add = Add_proto( tcc.tcc_get_symbol( TCL, 'Add' ) )
# ------------------

z = Add( 2, 5 )
print( z )

# ------------------
tcc.tcc_delete(TCL)
_=raw_input()
これ1本でOK。

コーディング量は Lua に比べて少ない!


本日はここまで。


luajit-tcc 学習は続く。


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


170408
スポンサーサイト

LuaJIT-tcc 学習:これって、コールバック処理?

2017-05-22 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-05-20)の記事「LuaJIT-tcc 学習:利用法まとめ」で、
  ・・・・・
  ・・・・・
  即ち、Cコードで、SUB 関数を定義し、即時に実行する。
  この時、SUB 関数は、
  ・・・・・
  ・・・・・
  パターンB:Lua の 自作 BBB 関数を呼ぶ
  ・・・・・
  ・・・・・
と書いているが、・・・・・

これって、所謂コールバック処理でしょうか?


まあ、それは置いておいて、
今回、データの共有が出来るのか?
確認してみた。

テスト・プログラムはつまらないもの:
メイン処理で作ったテーブルを(上記の)関数でアクセスできるか?
----- L_C_L_global.gsl
tcc = require 'tcc' ( 'libtcc' )
TCL = tcc.new()
TCL:set_output_type( 'output_memory' )
-------------------- 以上は、固定

function Lget(n) return tbl[n] end

-------------------
TCL:add_symbol( 'Lget', Lget, 'double(*)(int)' )

TCL:compile_string [[
double Lget( int );
double Cget( int n ){ return Lget( n ); }
]]
TCL:relocate( 'relocate_auto' )

Cget = TCL:get_symbol( 'Cget', 'double(*)(int)' )
-------------------

tbl = ffi.new( 'double[5]', 0.1, 1.2, 2.3, 3.4, 4.5 )
z = Cget(3) -- Lua から、C を呼ぶ。その C は、Lua を呼ぶ。
-- 「tbl」共有可能か?確認
print( z )
-------------------- 以下は、固定
TCL:delete()
これを実行すると。
結果は 3.4 となる。
これは正解ですネ。


つまり、グローバルデータは使える。

当然のことでしたか?


本日はここまで。


luajit-tcc 学習は続く。


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


170407

LuaJIT-tcc 学習:利用法まとめ

2017-05-20 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
先日(2017-05-13)の記事「LuaJIT-tcc:例題から学習」で、
幾つかのパターンについて学習したが、
その後の学習結果を含め、“tcc.lua”の利用パターンをまとめた。


最初に、'tcc.lua' モジュールを解読(?)した結果から、・・・・・

'libtcc.dll' の内部にある関数は以下の19個か?
TCCState* tcc_new( void );
void tcc_delete( TCCState* s );
void tcc_set_lib_path( TCCState* s, const char* path );
void tcc_set_error_func( TCCState* s, void* error_opaque, void ( *error_func )( void* opaque, const char* msg ) );
int tcc_set_options( TCCState* s, const char* str );
int tcc_add_include_path( TCCState* s, const char* pathname );
int tcc_add_sysinclude_path( TCCState* s, const char* pathname );
void tcc_define_symbol( TCCState* s, const char* sym, const char* value );
void tcc_undefine_symbol( TCCState* s, const char* sym );
int tcc_add_file( TCCState* s, const char* filename );
int tcc_compile_string( TCCState* s, const char* buf );
int tcc_set_output_type( TCCState* s, int output_type );
int tcc_add_library_path( TCCState* s, const char* pathname );
int tcc_add_library( TCCState* s, const char* libraryname );
int tcc_add_symbol( TCCState* s, const char* name, const void* val );
int tcc_output_file( TCCState* s, const char* filename );
int tcc_run( TCCState* s, int argc, char* *argv );
int tcc_relocate( TCCState* s1, void* ptr );
void* tcc_get_symbol( TCCState* s, const char* name );
これに対して、
'tcc.lua' が公開している関数は19個で、
大半(以下の14)は右から左:
TCCState* tcc_new()
void tcc_delete( s )
void tcc_set_lib_path( s, path )
void tcc_set_error_func( s, opaque, error_func )
int tcc_set_options( s, str )
int tcc_add_include_path( s, pathname )
int tcc_add_sysinclude_path( s, pathname )
void tcc_define_symbol( s, sym, value )
void tcc_undefine_symbol( s, sym )
int tcc_add_file( s, filename )
int tcc_compile_string( s, buf )
int tcc_add_library_path( s, pathname )
int tcc_add_library( s, libraryname )
int tcc_output_file( s, filename )
だが、
以下の5つでは若干の処理を行っている。
set_output_type( s, type )         -- 第2引数は、変換している
relocate( s, ptr ) -- 第2引数は、変換している
add_symbol( s, name, val, ctype ) -- 第3、4引数で処理をしている
get_symbol( s, name, ctype ) -- 第3引数で処理をしている
run( s, t ) -- 第2引数で処理をしている
'libtcc.dll' 直接使用では、
追加の処理が必要。

それで、 <紙>が欲しいのは以下の9個かナ?
TCCState* tcc_new( void );
void tcc_delete( TCCState* s );
int tcc_set_output_type( TCCState* s, int output_type );
int tcc_add_file( TCCState* s, const char* filename );
int tcc_add_symbol( TCCState* s, const char* name, const void* val );
int tcc_compile_string( TCCState* s, const char* buf );
int tcc_relocate( TCCState* s1, void* ptr );
int tcc_output_file( TCCState* s, const char* filename );
void* tcc_get_symbol( TCCState* s, const char* name );
以上を使ったもののまとめ。


初めに、単に DLL ファイルを作るパターンについて、・・・・・
これは、
先日の記事の(2)DLL ファイル( 'k_lib.dll' )を作るパターン

“Add”関数1つを定義した“k_lib.dll”を作る場合:
-------- make_dll.gsl -----------
tcc = require'tcc' ('libtcc')
TCL = tcc.new()
TCL:set_output_type( 'output_dll' )

-- ===== Cコード ===============
TCL:compile_string[[
#include <windows.h>
#define DLLExport __declspec ( dllexport )
DLLExport int Add( int x, int y ){
return x + y;
}
]]
TCL:output_file( 'k_lib.dll' )
TCL:delete()
とする。


次に、Cコードをコンパイルして即時に実行するパターン

当面考えられる全てのパターンを集めた場合を考える。

即ち、Cコードで、SUB 関数を定義し、即時に実行する。

この時、SUB 関数は、
パターンA:C の AAA 関数を呼ぶ
パターンX:Lua の 標準関数(例:math.sin)を呼ぶ
パターンB:Lua の 自作 BBB 関数を呼ぶ
パターンC:既存DLL にある CCC 関数を呼ぶ
これらのパターンを含めるとすると、
----- 以下2行は必須。
tcc = require'tcc' ('libtcc')
TCL = tcc.new()
----------

-- function BBB( x ) return ~ end -- 関数定義 -- パターンB の場合

TCL:set_output_type( 'output_memory' )

-- TCL:add_file( 'k_lib.dll' ) 既存 DLL ファイル -- パターンC の場合

-- TCL:add_symbol( 'BBB', BBB, 'int(*)( int, int )' ) -- パターンB の場合

-- TCL:add_symbol( 'sin', math.sin, 'double(*)(double)' ) -- パターンX の場合

TCL:compile_string [[

// -- double sin( double ) -- プロトタイプ宣言 -- パターンX の場合

// -- ここに、CCC 関数 のプロトタイプ宣言 -- パターンC の場合

// -- ここに、AAA 関数定義の Cコード -- パターンA の場合

double SUB( double x, double y ){ // SUB 関数のコード

double z;

// 各パターン( A, X, B, C ) の関数を利用するCコード

return z;
}
]]

TCL:relocate( 'relocate_auto' )
SUB = TCL:get_symbol( 'SUB', 'double(*)( double, double )' )

----- ここで、SUB を使う LuaJIT のコード

以上。
些か分かりにくいかナ?



ここで、パターンC の場合 に、
add_file 関数で指定するファイル名は、
既存の DLL ファイルの方が良かった。
つまり、
以前(2017-05-13)の記事「LuaJIT-tcc:例題から学習」の様に、
def ファイルを指定すると、
両方のファイルが必要となってしまう。


本日はここまで。


luajit-tcc 学習は続く。


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


170406,19

tcc 学習:libtcc 直接使用(成功)

2017-05-19 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-05-17)の記事「tcc 学習:libtcc 直接使用」では、

  libtcc1.a に関するエラー原因不明。

で終わっていた。


その後の学習で、原因が判明した。


一番大事なことは、

tcc への PATH を登録している場合、
カレントに、libtcc.dll を置いてはダメ。


と云うことでした。


カレントに置かなければ、libtcc1.a を見つける。
なので、libtcc1.a もカレントに置かなくて良い。
(置いても問題ないが、それはムダ)


そうすると、

  tcc_add_library_path( TCL, '.' )

の行もイラナイ。


つまり、
カレントには、(正しい?)use_libtcc_inline_C.gsl ダケで十分。


結局、以下のコードで十分:
----- use_libtcc_inline_C.gsl -----
-------- void* は、正確には TCCState*
ffi.cdef[[
void* tcc_new( void );
int tcc_set_output_type( void* s, int output_type );

int tcc_compile_string( void* s, const char* buf );
int tcc_relocate( void* s1, void* ptr );

void* tcc_get_symbol( void* s, const char* name );
void tcc_delete( void* s );
]]

-- =========================
tcc = ffi.load( 'libtcc' ) -- カレントに libtcc.dll は置かない
relocate_auto = ffi.cast( 'void*', 1 )

charA = |s| ffi.cast( 'char*', s )
-- =========================

TCL = tcc.tcc_new()
tcc.tcc_set_output_type( TCL, 0 ) -- 0 : run in memory

-- ===== Cコード =====
sss = [[ int Add( int x, int y ){
return x + y;
}
]]
tcc.tcc_compile_string( TCL, charA(sss) )

tcc.tcc_relocate( TCL, relocate_auto )

sym = tcc.tcc_get_symbol( TCL, charA('Add') )
Add = ffi.cast( 'int(*)( int, int )', sym )

-- ===== GSL Shell コード =====

z = Add( 2, 5 ); print( z )
print( Add( 10, 5 ) )

-- ===== 後処理 ============
tcc.tcc_delete(TCL)
_=io.read(1)
こんな感じ。

これでスッキリした。


本日はここまで。


luajit-tcc 学習は続く。


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


170406

tcc 学習:libtcc 直接使用

2017-05-17 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
先日(2017-05-12)の記事:
luajit-tcc:Tiny C Compiler 0.9.26 binding for LuaJIT」では、

  ・・・・・
  ・・・・・
  これって、
  以前(2017-05-03)の記事「tcc - Tiny C Compiler」で書いた、
  “libtcc”を使ったもの?
  ・・・・・
  ・・・・・
  案の定「tcc.lua」1つあれば使える。
  ・・・・・
  ・・・・・

と云うことで、
libtcc”はイラナイのだが、・・・・・

tcc.luaモジュールを学習して、
libtccを直接使ってみることに挑戦。


tcc.luaモジュールの他に、
・ ~/tcc/libtcc/  にある、libtcc.h
と、
・ ~/tcc/examples/ にある、libtcc_test.c
も参照した。


それで、
以前(2017-05-13)の記事「LuaJIT-tcc:例題から学習」で書いた、
“use_inline_C.gsl”を書き直した:
----- use_libtcc_inline_C.gsl -----
-------- void* は、正確には TCCState*
ffi.cdef[[
void* tcc_new( void );
int tcc_set_output_type( void* s, int output_type );
// #define TCC_OUTPUT_MEMORY 0 /* run in memory (default)
// #define TCC_OUTPUT_EXE 1 /* executable file
// #define TCC_OUTPUT_DLL 2 /* dynamic library
// ・・・・・・・・・・・・

int tcc_compile_string( void* s, const char* buf );
int tcc_relocate( void* s1, void* ptr );
// #define TCC_RELOCATE_AUTO (void*)1

void* tcc_get_symbol( void* s, const char* name );
void tcc_delete( void* s );
int tcc_add_library_path( void* s, const char* pathname );
]]

-- =========================
tcc = ffi.load( 'libtcc' ) -- カレントに libtcc.dll を配置
relocate_auto = ffi.cast( 'void*', 1 )

charA = |s| ffi.cast( 'char*', s )
-- =========================

TCL = tcc.tcc_new()
z = tcc.tcc_set_output_type( TCL, 0 )

-- ===== Cコード =====
sss = [[ int Add( int x, int y ){
return x + y;
}
]]
z = tcc.tcc_compile_string( TCL, charA(sss) )

-- この行が無いと、libtcc1.a が見つから無いエラー???
z = tcc.tcc_add_library_path( TCL, '.' ) -- カレントに libtcc1.a も配置

tcc.tcc_relocate( TCL, relocate_auto )

sym = tcc.tcc_get_symbol( TCL, charA('Add') )
Add = ffi.cast( 'int(*)( int, int )', sym )

-- ===== GSL Shell コード =====

z = Add( 2, 5 ); print( z )
print( Add( 10, 5 ) )

-- ===== 後処理 ============
tcc.tcc_delete(TCL)
_=io.read(1)
こんな感じかな。


libtcc1.a に関するエラー原因不明。


本日はここまで。


luajit-tcc 学習は続く。


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


170405

tcc 学習:オブジェクト性能

2017-05-15 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-05-13)の記事「LuaJIT-tcc:例題から学習」に続いて、
今回は、tcc で生成したオブジェクトの性能について学習。


tcc プロセッサ自体の性能については、
先日(2017-05-03)の記事「tcc - Tiny C Compiler」で書いた如く、

 ・FAST! tcc generates x86 code. No byte code overhead.
   Compile, assemble and link several times faster than GCC.
===
 ・早く! tccはx86コードを生成します。
   バイトコードオーバーヘッドはありません。 コンパイル、アセンブル、
   リンクはGCCより数倍高速です。

だそうですね。

そうすると、生成結果のプログラムの実行性能を知りたい。

例によって???
昨年9月(2016-09-23)の記事「LuaJIT vs LLVM/Clang」で書いた、
“フィボナッチ数を求めるプログラム”で実行時間を計測。

計測のためのプログラム:
----- fib.gsl ------
tcc = require'tcc' ('libtcc')
TCL = tcc.new()
TCL:set_output_type( 'output_memory' )
----------------------------
TCL:compile_string [[
int fib( int n ){
if( n < 2 ){ return n;
}else{ return fib(n-1) + fib(n-2);
}
}
]]
TCL:relocate( 'relocate_auto' )
fib = TCL:get_symbol( 'fib', 'int(*)( int )' )
-- ======================

local t=require'time'

Cst=t.time()
print( fib( 39 ) )
Cet=t.time()

print( Cet-Cst ) -- 0.515 秒

-- ====================
TCL:delete()
と云ったもの。

結果は、上記プログラム内コメントの通り。
これは、以前の LLVM/Clang での結果の -O3 無しに相当する。

つまり、
tcc のオブジェクトは、
最適化無し LLVM/Clang のオブジェクトと一緒。
LuaJIT に比べて、約 1.5 倍速い。


tcc は、MinGW に比べて、
コンパイル時間は数倍速く、オブジェクト性能は同等
(最適化機能は無し)
と云うこと?


本日はここまで。


luajit-tcc 学習は続く。


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


170404

LuaJIT-tcc:例題から学習

2017-05-13 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-05-12)の記事「luajit-tcc:Tiny C Compiler ・・・」で書いた、
同梱例題を基に、本格的(?)な学習を行った。

(1)例題の「base.lua」同様に、インラインCコードで関数を定義し、
  その場でそれを使う、GSL Shell プログラム:
  (追加でのファイル出力は無し)
-------- use_inline_C.gsl -----
tcc = require'tcc' ('libtcc')
TCL = tcc.new()
TCL:set_output_type( 'output_memory' )

-- ===== Cコード ==========
TCL:compile_string [[
int Add( int x, int y ){
return x + y;
}
]]
TCL:relocate( 'relocate_auto' )
Add = TCL:get_symbol( 'Add', 'int(*)( int, int )' )

-- ===== GSL Shell コード =======
z = Add( 2, 5 ); print( z )

-- ===== 後処理 =====
TCL:delete()
_=io.read(1)
で、実行は、
「use_inline_C.gsl」ファイルのダブルクリックで可。


(2)例題の「compile_exe.lua」を流用して、
  DLL ファイル( 'k_lib.dll' )を作るもの:
-------- make_dll.gsl -----
tcc = require'tcc' ('libtcc')
TCL = tcc.new()
TCL:set_output_type( 'output_dll' )

-- ===== Cコード =======
C_PG = [[
#include <windows.h>
#define DLLExport __declspec ( dllexport )
DLLExport int Add( int x, int y ){
return x + y;
}
]]
TCL:compile_string( C_PG )
TCL:output_file( 'k_lib.dll' )
TCL:delete()

-----------------------------
-- ===== 以下はテスト用 =====
klib = ffi.load( 'k_lib' )
ffi.cdef[[ int Add( int x, int y ); ]]

z = klib.Add( 2, 5 ); print( z )
_=io.read(1)
で、実行は、
「make_dll.gsl」ファイルのダブルクリックで可。
この時、同時に「k_lib.def」ファイルも出来る。


(3)例題の「add_symbol.lua」を流用して、
  DLL ファイル(例えば上記の'k_lib.dll')を使う Cコードの例:
-------- use_dll_inline_C.gsl ---
tcc = require'tcc' ('libtcc')
TCL = tcc.new()
TCL:set_output_type( 'output_memory' )
TCL:add_file( 'k_lib.def' ) -- DLL 情報

-- ===== Cコード ========
TCL:compile_string [[
int Add( int, int ); // DLL 内 関数プロトタイプ

int L_Add( int x, int y ){
return Add( x, y );
}
]]
TCL:relocate( 'relocate_auto' )
L_Add = TCL:get_symbol( 'L_Add', 'int(*)( int, int )' )

-- ===== GSL Shell コード =======
z = LAdd( 2, 5 ); print( z )

-- ===== 後処理 ==========
TCL:delete()
_=io.read(1)
で、実行は、
「use_dll_inline_C.gsl」ファイルのダブルクリックで可。
但し、'k_lib.def'、'k_lib.dll'も一緒に置いておく。


本日はここまで。


luajit-tcc 学習は続く。


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


170402,03

luajit-tcc:Tiny C Compiler 0.9.26 binding for LuaJIT

2017-05-12 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
Lua 向けの ライブラリでは、
基本Lua 用と、LuaJIT(GSL Shell)用とで、互換性が無い?

このことは、昨年3月(2016-03-15)の記事:
GSL Shell 学習:LuaJIT で IupLua は …」で書いている。

そして、昨年2月(2016-02-10)の記事:
GSL Shell 学習:LFS モジュール」で書いた、
LFSモジュールは、“LuaJIT”用のもので“Lua”用は別にある。

また、昨年9月(2016-09-05)の記事:
afxLua - MS Windows API Library」で書いた、
afxLuaライブラリは、“LuaJIT”用のもの。


そこで、
「LuaJIT library」で検索していたら、・・・・・

GitHub - Playermet/luajit-iup: IUP binding for LuaJIT
を見つけた。

だが、昨年4月(2016-04-28)の記事:
GSL Shell 学習:“IUP.lua”モジュール自作」で書いた、
自作 'IUP.lua' モジュール と同等?なもの。
イラナイ?


と、・・・・・

1段上を見た:
GitHub - Playermet
すると、
  Pinned repositories
に、
  luajit-tcc
  Tiny C Compiler 0.9.26 binding for LuaJIT
がある。

  “examples”フォルダには、4本のプログラムがある。

で、実質“tcc.lua”モジュール1本???


  Start using
では、
-- Windows
local tcc = require 'tcc' ('libtcc')
local tcc = require 'tcc' ('../some/path/libtcc.dll')
とあり、
その下に10行ちょっとのExample code
が載っている。

これって、
以前(2017-05-03)の記事「tcc - Tiny C Compiler」で書いた、
libtcc”を使ったもの?


早速、(右の「Clone or download」ボタンから)
ダウンロードした。
 「luajit-tcc-master.zip」 2016-01-02 付 4.91KB

ここで ( これまで保留していた ) tcc へのパスを登録した。
<紙>の場合は、D:/TOOL/Euler/tcc/

そうすると、
案の定「tcc.lua」1つあれば使える。
この1本は、“GSL Shell”に登録した。
<紙>の場合は、D:/TOOL/Lua/gsl-shell/gsl-shell/

そして、
4つの例題を試した。
「base.lua」「compile_exe.lua」「run.lua」と
「add_symbol.lua」

起動(実行)は、どこか作業用ディレクトリで、
gsl-shell  base.lua
等々で。


これは面白い。

libtcc”を使って見ようと思っていたが、
より使い勝手の良い“luajit-tcc”を学習しよう。


本日はここまで。


luajit-tcc 学習は続く。


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


170402

tcc 学習:call_lua51_Gen モジュール作成

2017-05-10 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-05-08)の記事「tcc 学習:既存 DLL を呼び出す DLL の作成」に続いて、
tcc の学習。

今回は、call_Lua51 の作成に関して学習。


これまでの学習から、

(1)“tiny_impdef”コマンドで、
  「lua51.dll」から「lua51.def」を作る。


(2)call_Lua51_Gen モジュールを tcc コードで作る:
// ----- call_Lua51_Gen.c -----
#include <windows.h>
#define DLLExport __declspec ( dllexport )

// -- lua51.dll 内 関数

void* luaL_newstate( void );
void luaL_openlibs( void* L );

int luaL_loadfilex( void* L, const char* fname, const char* mode );
int lua_pcall( void* L, int nargs, int nresults, int msgh );

void lua_getfield( void* L, int i , const char* name );
void lua_pushlightuserdata( void* L, void* p );
char* lua_pushstring( void* L, const char* s );

char* lua_tolstring( void* L, int index, size_t* len );
void lua_settop( void* L, int m ); // m == -(n) - 1
void lua_close( void* L );

//----------------
void* L; int z; char* SV; char buf[1025];

DLLExport char* call_Lua( char* PG, char* FN, void* IT, char* ST ){

L = luaL_newstate();
luaL_openlibs( L );

z = luaL_loadfilex( L, PG, "bt" );
z = lua_pcall( L, 0, 0, 0 ); // 1度実行

lua_getfield( L, -10002, FN );
lua_pushlightuserdata( L, IT );
lua_pushstring( L, ST );

lua_pcall( L, 2, 1, 0 ); // 引数 2 個, 戻り値 1 個

SV = lua_tolstring( L, -1, &z ); // 戻り値
strcpy( buf, SV );

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

return buf;

}
これに対して、
tcc  -shared  call_Lua51_Gen.c  lua51.def
コマンドで、「call_Lua51_Gen.dll」を生成。


(3)今作った call_Lua51_Gen を使うメインプログラムを作る:
今回は、取り敢えず“GSL Shell”を使った。
----- call_call_Lua51_Gen_dll.gsl -----
lua = ffi.load( 'call_Lua51_Gen' ) -- call_Lua51 モジュール
ffi.cdef[[
char* call_Lua( char* PG, char* FN, void* IT, char* ST );
]]
charA = |s| ffi.cast( 'char*', s )
Int32 = |s| ffi.cast( 'int32_t', 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 で実行するコード:( 'Lua51_Gen.lua'(下記)必要
-------------------------- 「lfs.dll」「time.lua」も必要
ss1=[[ print('Lua5.1---')
ffi.cdef[[ int rand(void);
double sqrt(double); ]]
ss2=[[
print( ffi.C.rand() ) -- 乱数生成
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))
-----------------------------------------

SV = lua.call_Lua(charA('Lua51_Gen.lua'),charA('Exec'),voidA(IT),charA(ST))
----------------------------- 中で実行!!!
-----------------------------------------
print( ffi.string(SV) ) -- 戻り値:文字列
print( IT[0] ) ----------- Lua5.1 実行結果
これで行ける。

実行には、
先月(2017-04-17)の記事「call_Lua 似非モジュール:Lua51 汎用・決定版
で作った「Lua51_Gen.lua」も必要。


本日はここまで。


tcc ( Tiny C Compiler ) 学習は続く。


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


170330

tcc 学習:既存 DLL を呼び出す DLL の作成

2017-05-08 :  PCクリニック
Python、C言語、Perl、グルコサミン、Firefox
前(2017-05-06)の記事「tcc 学習:lua52.dll 利用その他」に続いて、
dll の利用に関して学習。

今回は、既存 DLL を呼び出す DLL の作成に関して学習。

先日(2017-05-05)の記事「tcc 学習:同梱例題その他」で書いた、
既存の“test_dll.dll”から始める。

(1)“tiny_impdef test_dll.dll”コマンドで
  「test_dll.def」を作る

(2)「test_dll.dll」を使う「use_k_dll.c」を作る:
// ----- use_k_dll.c -----
#include <windows.h>
#define DLLExport __declspec ( dllexport )

int Add( int x, int y ); // これは、'test_dll.dll' 内の関数

DLLExport int add2( int x, int y ){
int z = Add( x, y );

char buf[256];
sprintf( buf, "%d", z );
printf( buf );

return 2*z;
}

(3)“tcc -shared use_k_dll.c test_dll.def”コマンドで、
  「use_k_dll.dll」を作る
  「use_k_dll.def」も出来る

(4)「use_k_dll.dll」を使う「Main_use_k_dll.c」を作る:
// ----- Main_use_k_dll.c -----
int add2( int x, int y ); // これは、'use_k_dll.dll' 内の関数

int main(){
int z = add2( 2, 5 );

char buf[256];
sprintf( buf, "%d", z );
printf( buf );

return 0;
}

(5)“tcc Main_use_k_dll.c use_k_dll.def”コマンドで、
  「Main_use_k_dlls.exe」を作る

※※「Main_use_k_dll.exe」の実行には、2つの dll が必要。


更に、
メインプログラムを GSL Shellで作ってみる:
----- Main_use_k_dll.gsl -----
libK = ffi.load('use_k_dll') -- dll 読み込み
---------- 中で、test_dll.dll の Add を呼んでいる

ffi.cdef[[
int add2( int x, int y ); // use_k_dll 内の関数宣言
]]

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

print( libK.add2( 2, 5 ) ) --- 出来る
の様に、
これまで通りに作れる。


本日はここまで。


tcc ( Tiny C Compiler ) 学習は続く。


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


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



おきてがみ

最新記事
カレンダー
04 | 2017/05 | 06
- 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
ブックマーク