|
|
|
2014/5/20(Tue) 21:12:43|NO.62130
hspでコールバック関数を扱えるようにするモジュールができました。
以下がそのモジュールとサンプルです。
#ifndef _MODCLBK_AS
#define global _MODCLBK_AS
#module "modclbk" clbk
#uselib "msvcrt.dll"
#func malloc "malloc" int
#uselib "user32.dll"
#func SendMessage "SendMessageA"
#uselib "kernel32.dll"
#func VirtualProtect "VirtualProtect" var,int,int,var
#modinit var clbkptr,int _hwnd,int _iparam,int argmax
// var clbkptr ... コールバック関数へのポインタ
// int _hwnd ... メッセージの送り先ウィンドウのハンドル
// int _iparam ... oncmdで使用するメッセージID
// int argmax ... 関数の引数の数
dim _x,1
if argmax>0{
dim clbk,44
if varptr(VirtualProtect):VirtualProtect clbk,176,$40,_x
clbk(0)=$83ec8b55,$45c720ec,$000000fc,$f845c700
clbk(4)=argmax,$e845c7|((varptr(malloc)&$ff)<<24),((varptr(malloc)&$ffffff00)>>8)|$c7000000,$0000ec45
clbk(8)=$45c70000,$f4|((varptr(SendMessage)&$ffffff)<<8),((varptr(SendMessage)&$ff000000)>>24)|$f8458b00,$5002e0c1
clbk(12)=$ffe84d8b,$04c483d1,$c7e44589,$0000f045
clbk(16)=$558d0000,$f055890c,$8be4458b,$0889084d
clbk(20)=$01e045c7,$eb000000,$e0558b09,$8901c283
clbk(24)=$458be055,$e04539f8,$4d8b1a7d,$04c183f0
clbk(28)=$8bf04d89,$458be055,$f04d8be4,$89fc498b
clbk(32)=$d5eb900c,$52e4558b,$50f8458b,$68|((_iparam&$ffffff)<<8)
clbk(36)=((_iparam&$ff000000)>>24)|$6800|((_hwnd&$ffff)<<16),((_hwnd&$ffff0000)>>16)|$4d8b0000,$83d1fff4,$458910c4
clbk(40)=$f045c7fc,$00000000,$8bfc458b,$00c35de5
}
if argmax==0{
dim clbk,13
if varptr(VirtualProtect):VirtualProtect clbk,52,$40,_x
clbk(0)=$83ec8b55,$45c708ec,$000000fc,$f845c700
clbk(4)=varptr(SendMessage),$006a006a,$68|((_iparam&$ffffff)<<8),((_iparam&$ff000000)>>24)|$6800|((_hwnd&$ffff)<<16)
clbk(8)=((_hwnd&$ffff0000)>>16)|$458b0000,$83d0fff8,$458910c4,$fc458bfc
clbk(12)=$c35de58b
}
clbkptr=varptr(clbk)
return
#uselib "msvcrt.dll"
#func global free__modclbk "free" int
//コールバック内で最後にかならず"free__modclbk lparam"を呼び出す。
#global
#endif
#if 0
#const idmes1 $8000
#uselib "user32.dll"
#func EnumWindows "EnumWindows" int,int
#func GetWindowText "GetWindowTextA" int,int,int
title "コールバックモジュール"
dim clbkptr,1
dim i,1
sdim tmpwns,64
sdim wns
newmod clbk,modclbk,clbkptr,hwnd,idmes1,2
//ここでは、
//clbkptrにhwndへidmes1を送る、
//引数が4つのコールバック関数を作っている
oncmd gosub *ew,idmes1
//ここでは、
//idmes1が送られてきたら
//*ewを呼ぶように設定している
EnumWindows clbkptr,2
;await 0
//ここで一部の処理の順番が入れ替わることがある
//例えばhen = 0:mes callfunc(hen,clbkptr,0)
//で、コールバック内でmesした時
title "トップレベルウィンドウ数:"+i
mesbox wns,640,480,4,0
stop
*ew
dupptr winh,lparam,wparam*4,4
//lparam には引数の配列へのメモリアドレスが、
//wparam には配列の要素数が格納されているので
//このようにして引数を受け取る
GetWindowText winh.0,varptr(tmpwns),64
wns = wns + str(winh(0)) + "\t" + tmpwns + "\n"
i++
free__modclbk lparam
//free__modclbk lparam は、returnする前にかならず行う
return 1
#endif
サンプルを実行するときは#if 0を#if 1にしてください。
modclbkは著作権フリーです。
modclbkの改変や、modclbkを組み込んだプログラムの公開などに対して、
制限は一切ありません。
もし改造したバージョンを公開される場合は、
オリジナルとの区別が付くようにしてください。
このモジュール本体のソースを公開される場合は、
可能であればこのページのURLを表示していただけると嬉しいです。
このスレッドでは、「このモジュールでこんなこともできた」というサンプルや
使ってみた感想も募集したいと思います。
| |
|
2014/5/25(Sun) 22:55:06|NO.62193
私は機械語がわからないですし、実行もしていないので見当はずれなことかもれませんが、少し気になったので投稿させていただきます。
機械語の生成部分(と思われる部分)で、(??? & 0x???)>>?? という部分がよく見られますが、
最初の???が負の値(つまりMSBが1)のとき、MSB寄りのビット値が1になると思います。
例:
x=(0x80000000&0xFF000000)>>24
mes strf("x=%d\n =$%08X",x,x)
/*
実行例
x=-128
=$FFFFFF80
/*
この辺りは考えられているのでしょうか?
見当はずれなら申し訳ないです。
|
|
2014/5/28(Wed) 22:18:05|NO.62233
HK2さん
ありがとうございました。
確かにそのとおりでした。
モジュールを下のように修正しました。
#ifndef _MODCLBK_AS
#define global _MODCLBK_AS
#module "modclbk" clbk
#defcfunc uintbitshiftright int data,int n
high=0
if data&$80000000{
high=1<<(31-n)//
}
return ((data&$7fffffff)>>n)|high
#uselib "msvcrt.dll"
#func malloc "malloc" int
#uselib "user32.dll"
#func SendMessage "SendMessageA"
#uselib "kernel32.dll"
#func VirtualProtect "VirtualProtect" var,int,int,var
#modinit var clbkptr,int _hwnd,int _iparam,int argmax
// var clbkptr ... コールバック関数へのポインタ
// int _hwnd ... メッセージの送り先ウィンドウのハンドル
// int _iparam ... oncmdで使用するメッセージID
// int argmax ... 関数の引数の数
dim _x,1
if argmax>0{
dim clbk,44
if varptr(VirtualProtect):VirtualProtect clbk,176,$40,_x
clbk(0)=$83ec8b55,$45c720ec,$000000fc,$f845c700
clbk(4)=argmax,$e845c7|((varptr(malloc)&$ff)<<24),uintbitshiftright(varptr(malloc)&$ffffff00,8)|$c7000000,$0000ec45
clbk(8)=$45c70000,$f4|((varptr(SendMessage)&$ffffff)<<8),uintbitshiftright(varptr(SendMessage)&$ff000000,24)|$f8458b00,$5002e0c1
clbk(12)=$ffe84d8b,$04c483d1,$c7e44589,$0000f045
clbk(16)=$558d0000,$f055890c,$8be4458b,$0889084d
clbk(20)=$01e045c7,$eb000000,$e0558b09,$8901c283
clbk(24)=$458be055,$e04539f8,$4d8b1a7d,$04c183f0
clbk(28)=$8bf04d89,$458be055,$f04d8be4,$89fc498b
clbk(32)=$d5eb900c,$52e4558b,$50f8458b,$68|((_iparam&$ffffff)<<8)
clbk(36)=uintbitshiftright(_iparam&$ff000000,24)|$6800|((_hwnd&$ffff)<<16),uintbitshiftright(_hwnd&$ffff0000,16)|$4d8b0000,$83d1fff4,$458910c4
clbk(40)=$f045c7fc,$00000000,$8bfc458b,$00c35de5
}
if argmax==0{
dim clbk,13
if varptr(VirtualProtect):VirtualProtect clbk,52,$40,_x
clbk(0)=$83ec8b55,$45c708ec,$000000fc,$f845c700
clbk(4)=varptr(SendMessage),$006a006a,$68|((_iparam&$ffffff)<<8),uintbitshiftright(_iparam&$ff000000,24)|$6800|((_hwnd&$ffff)<<16)
clbk(8)=uintbitshiftright(_hwnd&$ffff0000,16)|$458b0000,$83d0fff8,$458910c4,$fc458bfc
clbk(12)=$c35de58b
}
clbkptr=varptr(clbk)
return
#uselib "msvcrt.dll"
#func global free__modclbk "free" int
//コールバック内で最後にかならず"free__modclbk lparam"を呼び出す。
#global
#endif
| |
|
2014/7/13(Sun) 22:49:35|NO.62866
モジュールをバージョンアップしました。
これにより、
free__modclbkを呼ばなくてよい、ウィンドウメッセージに頼らなくなった等の
改良された部分を使うことができます。
以下がモジュールとサンプルです。
#ifndef _MODCLBK2_AS
#define global _MODCLBK2_AS
#module "modclbk" clbk
#defcfunc uintbitshiftright int data,int n
high=0
if data&$80000000{
high=1<<(31-n)//
}
return ((data&$7fffffff)>>n)|high
#uselib "msvcrt.dll"
#func malloc "malloc" int
#func free "free" int
#uselib "kernel32.dll"
#func VirtualProtect "VirtualProtect" var,int,int,var
#modinit var clbkptr,int argmax,var clbklb
// var clbkptr ... コールバック関数へのポインタ
// int argmax ... 関数の引数の数
// var clbklb ... 呼び出すサブルーチンが入った変数
dim _x,1
mref ctx,68
ilb=0
memcpy ilb,clbklb,4,0,0
code_callptr = lpeek(ctx,168 + 48)//
if argmax>0{
dim clbk,44
if varptr(VirtualProtect):VirtualProtect clbk,220,$40,_x
clbk(0)=$83ec8b55,$45c72cec,$000000fc,$f845c700
clbk(4)=argmax,(varptr(malloc)&$000000ff)<<24|$00e045c7,$c7000000|uintbitshiftright(varptr(malloc)&$ffffff00,8),((varptr(free)&$0000ffff)<<16)|$0000e445
clbk(8)=$45c70000|uintbitshiftright(varptr(free)&$ffff0000,16),((code_callptr&$00ffffff)<<8)|$000000ec,uintbitshiftright(code_callptr&$ff000000,24)|$f8458b00,$5002e0c1
clbk(12)=$ffe04d8b,$04c483d1,$c7d84589,(((varptr(ctx)+36)&$0000ffff)<<16)|$0000f445
clbk(16)=$45c70000|uintbitshiftright((varptr(ctx)+36)&$ffff0000,16),(((varptr(ctx)+40)&$00ffffff)<<8)|$000000dc,$f045c700|uintbitshiftright((varptr(ctx)+40)&$ff000000,24),varptr(ctx)+784
clbk(20)=$00e845c7,$8d000000,$55890c55,$d8458be8
clbk(24)=$89084d8b,$d445c708,$00000001,$558b09eb
clbk(28)=$01c283d4,$8bd45589,$4539f845,$8b1a7dd4
clbk(32)=$c183e84d,$e84d8904,$8bd4558b,$4d8bd845
clbk(36)=$fc498be8,$eb900c89,$f4558bd5,$89f8458b
clbk(40)=$dc4d8b02,$89d8558b,(ilb&$0000ffff)<<16|$00006811,$458b0000|uintbitshiftright(ilb&$ffff0000,16)
clbk(44)=$83d0ffec,$4d8b04c4,$89118bf0,$45c7fc55
clbk(48)=$000000e8,$d8458b00,$e44d8b50,$c483d1ff
clbk(52)=$04c48304,$8bfc458b,$00c35de5//
}
if argmax==0{
dim clbk,13
if varptr(VirtualProtect):VirtualProtect clbk,88,$40,_x
clbk(0)=$83ec8b55,$45c714ec,$000000fc,$f045c700
clbk(4)=code_callptr,(((varptr(ctx)+36)&$000000ff)<<24)|$00f845c7,$c7000000|uintbitshiftright((varptr(ctx)+36)&$ffffff00,8),(((varptr(ctx)+40)&$0000ffff)<<16)|$0000ec45
clbk(8)=$45c70000|uintbitshiftright((varptr(ctx)+40)&$ffff0000,16),(((varptr(ctx)+784)&$00ffffff)<<8)|$000000f4,$f8458b00|uintbitshiftright((varptr(ctx)+784)&$ff000000,24),$000000c7
clbk(12)=$4d8b0000,$0001c7ec,$68000000,ilb
clbk(16)=$fff0558b,$04c483d2,$8bf4458b,$fc4d8908
clbk(20)=$8bfc458b,$00c35de5
}
clbkptr=varptr(clbk)
return
#global
#endif
#if
#uselib "user32.dll"
#func EnumWindows "EnumWindows" int,int
#func GetWindowText "GetWindowTextA" int,int,int
title "コールバックモジュール"
dim clbkptr,1
dim i,1
sdim tmpwns,64
sdim wns
//ここは変更されました。↓
ewlb=*ew
newmod clbk,modclbk,clbkptr,2,ewlb
//ここでは、
//clbkptrにewlbを呼ぶ、
//引数が2つのコールバック関数を作っている
// oncmd gosub *ew,idmes1
//ここでは、
//メッセージの設定をする必要がない
EnumWindows clbkptr,2
;await 0
//ここで一部の処理の順番が入れ替わることはなくなった
title "トップレベルウィンドウ数:"+i
mesbox wns,640,480,4,0
stop
*ew
dupptr winh,lparam,wparam*4,4
//lparam には引数の配列へのメモリアドレスが、
//wparam には配列の要素数が格納されているので
//このようにして引数を受け取る
GetWindowText winh.0,varptr(tmpwns),64
wns = wns + str(winh(0)) + "\t" + tmpwns + "\n"
i++
// free__modclbk lparam
//free__modclbk lparam は、する必要がない
return 1
#endif
| |
|
2014/9/16(Tue) 21:20:51|NO.65032
質問ってこのスレッドにしていいでしょうか?
DLLなどなるべく同梱しなくないため、ちょくとさんのhscallbk.dllを使って書かれたサンプルをtds12さんのモジュールで置き換えようと考えています
コールバック関数はよくわからないため、まずはhscallbk.dllのサンプルをmodclbkで置き換えています
しかしsample2がうまく出来ません
おかしいところはどこでしょうか…
hscallbk.dllのsample2
;
; EnumFontFamiliesEx() によるフォントファミリ取得サンプル
;
#include "gdi32.as"
#include "hscallbk.as"
; コールバック関数の関数形式を定義
; ( DLL名および関数名はダミー (空文字列) )
; ( int, double, str, comobj 型引数のみ指定可能 )
#uselib ""
#func EnumFontFamExProc "" int,int,int,int
#define SHIFTJIS_CHARSET 128
setcallbk Proc, EnumFontFamExProc, *OnEnumFontFamExProc
dim logfont, 15
poke logfont, 23, SHIFTJIS_CHARSET
notesel fontname
EnumFontFamiliesEx hdc, varptr(logfont), varptr(Proc), 0, 0
mesbox fontname, ginfo_winx, ginfo_winy
stop
*OnEnumFontFamExProc
dupptr elfex, callbkarg(0), 60
getstr name, elfex, 28
if peek(name,0) != '@' {
; 横書き用フォントのみ取り出す
noteadd name, -1
}
return 1
modclbkに置き換えたもの
#include "modclbk.as"
#include "gdi32.as"
#define SHIFTJIS_CHARSET 128
dim Proc,1
pOnEnumFontFamExProc = *OnEnumFontFamExProc
newmod clbk,modclbk,Proc,4,pOnEnumFontFamExProc
dim logfont, 15
poke logfont, 23, SHIFTJIS_CHARSET
notesel fontname
EnumFontFamiliesEx hdc, varptr(logfont),Proc, 0, 0
mesbox fontname, ginfo_winx, ginfo_winy
stop
*OnEnumFontFamExProc
dupptr winh,lparam,wparam*4,4
dupptr elfex, winh(0), 60
getstr name, elfex, 28
if peek(name,0) != '@' {
; 横書き用フォントのみ取り出す
noteadd name, -1
}
return 1
フォント名が最初の一つしか取得出来ません
| |
|
2014/9/16(Tue) 23:11:48|NO.65035
>質問ってこのスレッドにしていいでしょうか?
していただけると嬉しいです。
何より、使おうという人がいてうれしいです。
>フォント名が最初の一つしか取得出来ません
こちらでもそうなりました。
コールバック用ルーチン内でdialogを行ったところ
1回しか出なかったので、
戻り値が、0になっているのかと疑いました。
しかし、戻り値は、0以外であるように見えます。
(callfuncで調べました)
EnumFontFamiliesExという関数は初めて注意して見たので
詳しいことはまだ理解できていませんが、
logfontの指定部分も同じことをしているようにしか見えず、
ますます私にもわかりません。
modclbkの使い方としては、
おかしなところはないように見えます。
申し訳ないことですが、
Footy2のコールバックや
ウィンドウのサブクラス化を
試してみてください。
|
|
2014/10/16(Thu) 23:25:01|NO.65591
モジュールをバージョンアップしました。
これにより、バグが修正修正されたモジュールを使うことができます。
前回のモジュールとは互換性があります。
kanahironさんのおかげでこのバグに気づくことができました。
ありがとうございました。
これで、フォントの二つ目以降も取得できるようになりました。
↓がそのモジュールです。
#ifndef _MODCLBK_AS
#define global _MODCLBK_AS
#module "modclbk" clbk
#ifndef _MODBITSHIFTRIGHT
#define _MODBITSHIFTRIGHT
#defcfunc uintbitshiftright int data,int n
high=0
if data&$80000000{
high=1<<(31-n)//
}
return ((data&$7fffffff)>>n)|high
#endif
#uselib "msvcrt.dll"
#func malloc "malloc" int
#func free "free" int
#uselib "kernel32.dll"
#func VirtualProtect "VirtualProtect" var,int,int,var
#modinit var clbkptr,int argmax,var clbklb
// var clbkptr ... コールバック関数へのポインタ
// int argmax ... 関数の引数の数
// var clbklb ... 呼び出すサブルーチンが入った変数
dim _x,1
mref ctx,68
ilb=0
memcpy ilb,clbklb,4,0,0
code_callptr = lpeek(ctx,168 + 48)//
if argmax>0{
dim clbk,56
if varptr(VirtualProtect):VirtualProtect clbk,224,$40,_x
clbk(0)=$83ec8b55,$45c72cec,$000000fc,$f845c700
clbk(4)=argmax,(varptr(malloc)&$000000ff)<<24|$00e045c7,$c7000000|uintbitshiftright(varptr(malloc)&$ffffff00,8),((varptr(free)&$0000ffff)<<16)|$0000e445
clbk(8)=$45c70000|uintbitshiftright(varptr(free)&$ffff0000,16),((code_callptr&$00ffffff)<<8)|$000000ec,uintbitshiftright(code_callptr&$ff000000,24)|$f8458b00,$5002e0c1
clbk(12)=$ffe04d8b,$04c483d1,$c7d84589,(((varptr(ctx)+36)&$0000ffff)<<16)|$0000f445
clbk(16)=$45c70000|uintbitshiftright((varptr(ctx)+36)&$ffff0000,16),(((varptr(ctx)+40)&$00ffffff)<<8)|$000000dc,$f045c700|uintbitshiftright((varptr(ctx)+40)&$ff000000,24),varptr(ctx)+784
clbk(20)=$00e845c7,$8d000000,$55890c55,$d8458be8
clbk(24)=$89084d8b,$d445c708,$00000001,$558b09eb
clbk(28)=$01c283d4,$8bd45589,$4539f845,$8b1a7dd4
clbk(32)=$c183e84d,$e84d8904,$8bd4558b,$4d8bd845
clbk(36)=$fc498be8,$eb900c89,$f4558bd5,$89f8458b
clbk(40)=$dc4d8b02,$89d8558b,(ilb&$0000ffff)<<16|$00006811,$458b0000|uintbitshiftright(ilb&$ffff0000,16)
clbk(44)=$83d0ffec,$4d8b04c4,$89118bf0,$45c7fc55
clbk(48)=$000000e8,$d8458b00,$e44d8b50,$c483d1ff
clbk(52)=$04c48304,$8bfc458b,((((argmax*4)&$ffff)&$ff)<<24)|$00c25de5,((argmax*4)&$ff00)>>8
}
if argmax==0{
dim clbk,13
if varptr(VirtualProtect):VirtualProtect clbk,88,$40,_x
clbk(0)=$83ec8b55,$45c714ec,$000000fc,$f045c700
clbk(4)=code_callptr,(((varptr(ctx)+36)&$000000ff)<<24)|$00f845c7,$c7000000|uintbitshiftright((varptr(ctx)+36)&$ffffff00,8),(((varptr(ctx)+40)&$0000ffff)<<16)|$0000ec45
clbk(8)=$45c70000|uintbitshiftright((varptr(ctx)+40)&$ffff0000,16),(((varptr(ctx)+784)&$00ffffff)<<8)|$000000f4,$f8458b00|uintbitshiftright((varptr(ctx)+784)&$ff000000,24),$000000c7
clbk(12)=$4d8b0000,$0001c7ec,$68000000,ilb
clbk(16)=$fff0558b,$04c483d2,$8bf4458b,$fc4d8908
clbk(20)=$8bfc458b,$00c35de5
}
clbkptr=varptr(clbk)
return
#global
#endif
また、コンテストにも出品しました。
zipの中にはサンプル3つが含まれています。
http://dev.onionsoft.net/seed/info.ax?id=838
宣伝でした。
| |
|
2015/1/4(Sun) 22:44:39|NO.66878
モジュールをバージョンアップしました。
前回のモジュールとは互換性がありません。
無いとは思いますが、大きな変更のために問題が起こるかもしれません。
もし起こったら教えてください。
また、さらに大きな変更を予定しています。
今回のモジュールの変更内容は↓
・モジュール変数を使用しないようにしたこと
(ただし、hsp2cでは「変数名が指定されていない」とエラーになります)
・cdecl規約に対応したこと
です。
以下が、そのモジュールとサンプルです。
#ifndef _MODCLBK3A1_AS
#define global _MODCLBK3A1_AS
#define global newclbk3(%1,%2 = 0,%3,%4 = 0) tmpclbklb@modclbk3a1=%3:%1=_newclbk3(%2,tmpclbklb@modclbk3a1,%4)
//新しい関数ポインタを取得する
// %1...関数ポインタを受け取る変数
// %2...引数の数
// %3...呼び出されるラベル
// %4...作成のモード(CLBKMODE)
#define global clbkargprotect(%1) lp@modclbk3a1=lparam:wp@modclbk3a1=wparam:dupptr args@modclbk3a1,lp@modclbk3a1,wp@modclbk3a1*4,4:dim %1,wp@modclbk3a1:memcpy %1,args@modclbk3a1,wp@modclbk3a1*4
//引数を取得する
// %1...引数を受け取るための変数
#module "modclbk3a1"
#ifndef _MODBITSHIFTRIGHT
#define _MODBITSHIFTRIGHT
#defcfunc uintbitshiftright int data,int n
high=0
if data&$80000000{
high=1<<(31-n)//
}
return ((data&$7fffffff)>>n)|high
#endif
#uselib "msvcrt.dll"
#cfunc malloc "malloc" int
#func free "free" int
#uselib "kernel32.dll"
#func VirtualProtect "VirtualProtect" var,int,int,var
#define global CLBKMODE_CDECL $00000001
// 呼び出し規約をcdeclに設定する
#defcfunc _newclbk3 int _argmax,var clbklb,int mode
// int _argmax ... 関数の引数の数
// var clbklb ... 呼び出すサブルーチンが入った変数
// int mode ... コールバック関数のモード(CLBKMODE_)
dim _x,1
mref ctx,68
ilb=0
memcpy ilb,clbklb,4,0,0
argmax = _argmax
if inited == 0{
inited = 1
dim ptrtable
ptrmax = 0
}
code_callptr = lpeek(ctx,168 + 48)//
if argmax>0{
dim clbk,56
clbk(0)=$83ec8b55,$45c72cec,$000000fc,$f845c700
clbk(4)=argmax,(varptr(malloc)&$000000ff)<<24|$00e045c7,$c7000000|uintbitshiftright(varptr(malloc)&$ffffff00,8),((varptr(free)&$0000ffff)<<16)|$0000e445
clbk(8)=$45c70000|uintbitshiftright(varptr(free)&$ffff0000,16),((code_callptr&$00ffffff)<<8)|$000000ec,uintbitshiftright(code_callptr&$ff000000,24)|$f8458b00,$5002e0c1
clbk(12)=$ffe04d8b,$04c483d1,$c7d84589,(((varptr(ctx)+36)&$0000ffff)<<16)|$0000f445
clbk(16)=$45c70000|uintbitshiftright((varptr(ctx)+36)&$ffff0000,16),(((varptr(ctx)+40)&$00ffffff)<<8)|$000000dc,$f045c700|uintbitshiftright((varptr(ctx)+40)&$ff000000,24),varptr(ctx)+784
clbk(20)=$00e845c7,$8d000000,$55890c55,$d8458be8
clbk(24)=$89084d8b,$d445c708,$00000001,$558b09eb
clbk(28)=$01c283d4,$8bd45589,$4539f845,$8b1a7dd4
clbk(32)=$c183e84d,$e84d8904,$8bd4558b,$4d8bd845
clbk(36)=$fc498be8,$eb900c89,$f4558bd5,$89f8458b
clbk(40)=$dc4d8b02,$89d8558b,(ilb&$0000ffff)<<16|$00006811,$458b0000|uintbitshiftright(ilb&$ffff0000,16)
clbk(44)=$83d0ffec,$4d8b04c4,$89118bf0,$45c7fc55
clbk(48)=$000000e8,$d8458b00,$e44d8b50,$c483d1ff
if mode&CLBKMODE_CDECL:argmax = 0
clbk(52)=$04c48304,$8bfc458b,((((argmax*4)&$ffff)&$ff)<<24)|$00c25de5,((argmax*4)&$ff00)>>8
clbkptr = malloc(224)
dupptr clbkfunc,clbkptr,224,4
memcpy clbkfunc,clbk,224
VirtualProtect clbkfunc,224,$40,_x
}
if argmax==0{
dim clbk,13
clbk(0)=$83ec8b55,$45c714ec,$000000fc,$f045c700
clbk(4)=code_callptr,(((varptr(ctx)+36)&$000000ff)<<24)|$00f845c7,$c7000000|uintbitshiftright((varptr(ctx)+36)&$ffffff00,8),(((varptr(ctx)+40)&$0000ffff)<<16)|$0000ec45
clbk(8)=$45c70000|uintbitshiftright((varptr(ctx)+40)&$ffff0000,16),(((varptr(ctx)+784)&$00ffffff)<<8)|$000000f4,$f8458b00|uintbitshiftright((varptr(ctx)+784)&$ff000000,24),$000000c7
clbk(12)=$4d8b0000,$0001c7ec,$68000000,ilb
clbk(16)=$fff0558b,$04c483d2,$8bf4458b,$fc4d8908
clbk(20)=$8bfc458b,$00c35de5
clbkptr = malloc(88)
dupptr clbkfunc,clbkptr,88,4
memcpy clbkfunc,clbk,88
VirtualProtect clbkfunc,88,$40,_x
}
ptrtable(ptrmax)=clbkptr
ptrmax++
return clbkptr
#deffunc modclbk_term onexit
repeat ptrmax
free ptrtable(cnt)
loop
ptrmax=0
return
#global
#endif
#if 0
#uselib "user32.dll"
#func EnumWindows "EnumWindows" int,int
#func GetWindowText "GetWindowTextA" int,int,int
title "コールバックモジュール"
dim clbkptr,1
dim i,1
sdim tmpwns,64
sdim wns
newclbk3 clbkptr,2,*ew
newclbk3 clbkptr2,2,*ew2
//ここでは、
//clbkptrにewlbを呼ぶ、
//引数が2つのコールバック関数を2つ作っている
EnumWindows clbkptr,0
i = 0
EnumWindows clbkptr2,0
title "トップレベルウィンドウ数:"+i
mesbox wns,640,480,4,0
stop
*ew
clbkargprotect winh
//引数を受け取りたい変数を指定するだけで良い。
//また、間違ってこの変数に代入しても
//もう一度受け取れば正しい引数になる。
GetWindowText winh.0,varptr(tmpwns),64
wns = wns + str(winh(0)) + "\t" + tmpwns + "\n"
return 1
*ew2
i++
return 1
#endif
| |
|
2015/1/4(Sun) 22:54:43|NO.66879
過去ログに行かない間に書かなければとあわててしまいました。
hsp2cはvarptr(関数)には対応していませんでしたね。
後で直しておきます。
|
|
2015/4/18(Sat) 20:14:56|NO.68623
すみませんが、空投稿します。
急いで更新します。
|
|
2015/4/18(Sat) 21:47:26|NO.68633
> 急いで更新します。
この「コールバック用モジュール」は、どの程度利用できるのでしょうか?
こちらも興味があり使いたい派です。
自作のフリーソフトに組み込んだときの利用規約とか、
商用利用?(電子ブックなど)はどのようになるのでしょうか?
|
|
2015/4/18(Sat) 23:14:24|NO.68634
以下の通り、更新いたします。
この更新によって、thiscall規約へ対応します。
また、引数数0を指定した場合のバグも修正いたしました。
前に書いた通りhsp2cへの対応を目指しましたが、
関数へのvarptrやモジュール変数の排除などを行ったものの、
hsp2cのサブルーチンジャンプが非同期であったため現在でも正しく動作せず、
また、コンパイルしてもマルウェアとして認識され、実行すらできませんので、
hsp2cでの使用はお勧めいたしません。
modclbk3a1との互換を目指しましたが、
共存はお勧めいたしません。
スクリプト中includeの階層構造内では、トップのファイルで最新のヘッダを
includeすることをお勧めいたします。
#ifndef _MODCLBK3B1_AS
#ifdef _MODCLBK3A1_AS
#undef _MODCLBK3A1_AS
#undef newclbk3
#undef clbkargprotect
#undef CLBKMODE_CDECL
#undef _newclbk3
#undef modclbk_term
#endif
#define global _MODCLBK3A1_AS
#define global _MODCLBK3B1_AS
#define global newclbk3(%1,%2 = 0,%3,%4 = 0) tmpclbklb@modclbk3a1=%3:%1=_newclbk3(%2,tmpclbklb@modclbk3a1,%4)
//新しい関数ポインタを取得する
// %1...関数ポインタを受け取る変数
// %2...引数の数
// %3...呼び出されるラベル
// %4...作成のモード(CLBKMODE)
#define global clbkargprotect(%1) lp@modclbk3a1=lparam:wp@modclbk3a1=wparam:dupptr args@modclbk3a1,lp@modclbk3a1,wp@modclbk3a1*4,4:dim %1,wp@modclbk3a1:memcpy %1,args@modclbk3a1,wp@modclbk3a1*4
//引数を取得する
// %1...引数を受け取るための変数
#module "modclbk3b1"
#define ctype uintbitshiftright(%1,%2) (((%1&$7fffffff)>>%2)|((1&(%1>>31))<<(31-%2)))
#uselib "msvcrt.dll"
#cfunc malloc "malloc" int
#func free "free" int
#uselib "kernel32.dll"
#func VirtualProtect "VirtualProtect" var,int,int,var
#cfunc LoadLibrary "LoadLibraryA" sptr
#cfunc GetProcAddress "GetProcAddress" int,sptr
#func FreeLibrary "FreeLibrary" int
#define global CLBKMODE_CDECL $00000001
// 呼び出し規約をcdeclに設定する
// 呼び出し規約をthiscallに設定する
#defcfunc _newclbk3 int _argmax,var clbklb,int mode
// int _argmax ... 関数の引数の数
// var clbklb ... 呼び出すサブルーチンが入った変数
// int mode ... コールバック関数のモード(CLBKMODE_)
dim _x,1
mref ctx,68
ilb=0
memcpy ilb,clbklb,4,0,0
argmax = _argmax
if inited == 0{
inited = 1
dim ptrtable
ptrmax = 0
hcrt = LoadLibrary("msvcrt.dll")
ptrtomalloc = GetProcAddress(hcrt,"malloc")
ptrtofree = GetProcAddress(hcrt,"free")
thisptr = 0
}
code_callptr = lpeek(ctx,168 + 48)//
if argmax>0{
dim clbk,57
clbk(0) = $83ec8b55,$45c730ec,$000000fc,$f845c700
clbk(4) = $00000000,$00e045c7,$c7000000,$0000e445
clbk(8) = $45c70000,$000000ec,$d845c700,$00000000
clbk(12) = $8bd84d89,$e0c1f845,$4d8b5002,$83d1ffe0
clbk(16) = $458904c4,$f445c7d4,$00000000,$00dc45c7
clbk(20) = $c7000000,$0000f045,$45c70000,$000000e8
clbk(24) = $0c558d00,$8be85589,$4d8bd445,$c7088908
clbk(28) = $0001d045,$09eb0000,$83d0558b,$558901c2
clbk(32) = $f8458bd0,$7dd04539,$e84d8b1a,$8904c183
clbk(36) = $558be84d,$d4458bd0,$8be84d8b,$0c89fc49
clbk(40) = $8bd5eb90,$458bf455,$8b0289f8,$558bdc4d
clbk(44) = $681189d4,$00000000,$ffec458b,$04c483d0
clbk(48) = $8bf04d8b,$fc558911,$00e845c7,$8b000000
clbk(52) = $8b50d445,$d1ffe44d,$8b04c483,$e58bfc45
clbk(56) = $0000c25d
lpoke clbk,$10,argmax:lpoke clbk,$17,ptrtomalloc:lpoke clbk,$1e,ptrtofree
lpoke clbk,$25,code_callptr:lpoke clbk,$2c,varptr(thisptr)
lpoke clbk,$48,varptr(ctx) + 36:lpoke clbk,$4f,varptr(ctx) + 40
lpoke clbk,$56,varptr(ctx) + 784:lpoke clbk,$b4,ilb
if ((mode & $f) == CLBKMODE_CDECL) == 0:wpoke clbk,$e2,argmax & $ffff
funcsize = 228
}
if argmax==0{
dim clbk,25
clbk(0) = $83ec8b55,$45c718ec,$000000fc,$f045c700
clbk(4) = $00000000,$00f845c7,$c7000000,$000045c7
clbk(8) = $45c70000,$000000f4,$ec45c700,$00000000
clbk(12) = $8bec4d89,$00c7f845,$00000000,$c7e84d8b
clbk(16) = $00000001,$00006800,$558b0000,$83d2fff0
clbk(20) = $458b04c4,$89088bf4,$458bfc4d,$5de58bfc
clbk(24) = $000000c3
lpoke clbk,$10,code_callptr:lpoke clbk,$17,varptr(ctx) + 36
lpoke clbk,$1e,varptr(ctx) + 40:lpoke clbk,$46,ilb
funcsize = 100
}
clbkptr = malloc(funcsize)
dupptr clbkfunc,clbkptr,funcsize,4
memcpy clbkfunc,clbk,funcsize
VirtualProtect clbkfunc,funcsize,$40,_x
ptrtable(ptrmax) = clbkptr
ptrmax++
return clbkptr
#defcfunc clbk_getthisptr
//Thisポインタを取得する。
//コールバックとして呼び出された直後に別変数へコピーしなければならない。
return thisptr
#deffunc modclbk_term onexit
repeat ptrmax
free ptrtable(cnt)
loop
if inited{
FreeLibrary hcrt
}
ptrmax = 0
return
#global
#endif
>組み込んだときの利用規約とか
このスレッドの最初で書いた通り、
modclbkは著作権フリーです。
modclbkの改変や、modclbkを組み込んだプログラムの公開などに対して、
制限は一切ありません。
もし改造したバージョンを公開される場合は、
オリジナルとの区別が付くようにしてください。
このモジュール本体のソースを公開される場合は、
可能であればこのページのURLを表示していただけると嬉しいです。
ということです。
つまり、無料ソフトに組み込んでソースを非公開にしても、
有料ソフトに組み込んで金儲けをしても、
このモジュールをそのまま再配布して1兆円儲けても、
このモジュールを改造して世界中に公開しても、
全て自由です。
ただし、明示し忘れていましたが、
このモジュールは
無保証
です。
機械語を直接書いた部分が含まれていますので、
本当にパソコンがクラッシュする可能性もありますが、
私に責任を求めないでください。
何かバグを見つけた場合には、このスレッドに書き込んでいただけると、
ありがたいです。
スクリプトにバグを発見したため、再投稿いたしました。
| |
|
2015/4/18(Sat) 23:54:25|NO.68635
> 私に責任を求めないでください。
> スクリプトにバグを発見したため、再投稿いたしました。
了解。
|
|
2015/4/24(Fri) 22:01:22|NO.68737
_MODCLBK3A1_ASは正常に動作するのですが
_MODCLBK3B1_ASでは「システムエラーが発生しました」と強制終了します
newclbk3命令は通りますが、コールバック関数を呼び出すと落ちてしまいます
|
|
2015/4/24(Fri) 23:12:09|NO.68739
再現もできず原因もわからなかったのですが、
少しだけ記述に間違いがあったので、
以下に示します。
newclbk3の#define行を
#define global newclbk3(%1,%2 = 0,%3,%4 = 0) tmpclbklb@modclbk3b1=%3:%1=_newclbk3(%2,tmpclbklb@modclbk3b1,%4)
のように、
clbkargprotectの#define行を
#define global clbkargprotect(%1) lp@modclbk3b1=lparam:wp@modclbk3b1=wparam:dupptr args@modclbk3b1,lp@modclbk3b1,wp@modclbk3b1*4,4:dim %1,wp@modclbk3b1:memcpy %1,args@modclbk3b1,wp@modclbk3b1*4
のように修正してみてください。
私の環境ではうまく動いたのですが、
あなたの環境と状況を教えて下さい。
・メモリは足りていますか
・モジュールが書き換わっていませんか
・newclbk3をどのような引数で呼び出しましたか
・なんという関数にコールバックを渡しましたか
・サブルーチンのスクリプトは実行されませんでしたか
実行された場合は引数取得が成功しましたか
あるいはreturnまで無事でしたか
このモジュールの技術的制限を念のため書いておくと、
・引数の数が13bitで表せないサイズになると正しく動作しない
・引数の型はすべて4ビット符号付き整数値で取得される
・引数の合計バイト数が4で割り切れない関数は作れない
・引数数がマイナスの場合に対応していない(バグとも言える)
です。
引数数1以上ではテストしましたが、0の場合はテストしていないので
バグの可能性が高いです。
と、書きながら引数数0で試したところエラーが発生しました。
しかし念のためエラーが起きた環境を教えて下さい。
|
|
2015/4/24(Fri) 23:50:08|NO.68740
以下のとおり更新いたします。
これにより、引数数0時のシステムエラーが起こるバグが修正されます。
#ifndef _MODCLBK3B2_AS
#ifdef _MODCLBK3A1_AS
#undef _MODCLBK3A1_AS
#undef newclbk3
#undef clbkargprotect
#undef CLBKMODE_CDECL
#undef _newclbk3
#undef modclbk_term
#endif
#ifdef _MODCLBK3B2_AS
#undef clbk_getthisptr
#endif
#define global _MODCLBK3A1_AS
#define global _MODCLBK3B1_AS
#define global _MODCLBK3B2_AS
#define global newclbk3(%1,%2 = 0,%3,%4 = 0) tmpclbklb@modclbk3b2=%3:%1=_newclbk3(%2,tmpclbklb@modclbk3b2,%4)
//新しい関数ポインタを取得する
// %1...関数ポインタを受け取る変数
// %2...引数の数
// %3...呼び出されるラベル
// %4...作成のモード(CLBKMODE)
#define global clbkargprotect(%1) lp@modclbk3b2=lparam:wp@modclbk3b2=wparam:dupptr args@modclbk3b2,lp@modclbk3b2,wp@modclbk3b2*4,4:dim %1,wp@modclbk3b2:memcpy %1,args@modclbk3b2,wp@modclbk3b2*4
//引数を取得する
// %1...引数を受け取るための変数
#module "modclbk3b2"
#define ctype uintbitshiftright(%1,%2) (((%1&$7fffffff)>>%2)|((1&(%1>>31))<<(31-%2)))
#uselib "msvcrt.dll"
#cfunc malloc "malloc" int
#func free "free" int
#uselib "kernel32.dll"
#func VirtualProtect "VirtualProtect" var,int,int,var
#cfunc LoadLibrary "LoadLibraryA" sptr
#cfunc GetProcAddress "GetProcAddress" int,sptr
#func FreeLibrary "FreeLibrary" int
#define global CLBKMODE_CDECL $00000001
// 呼び出し規約をcdeclに設定する
// 呼び出し規約をthiscallに設定する
#defcfunc _newclbk3 int _argmax,var clbklb,int mode
// int _argmax ... 関数の引数の数
// var clbklb ... 呼び出すサブルーチンが入った変数
// int mode ... コールバック関数のモード(CLBKMODE_)
dim _x,1
mref ctx,68
ilb=0
memcpy ilb,clbklb,4,0,0
argmax = _argmax
if inited == 0{
inited = 1
dim ptrtable
ptrmax = 0
hcrt = LoadLibrary("msvcrt.dll")
ptrtomalloc = GetProcAddress(hcrt,"malloc")
ptrtofree = GetProcAddress(hcrt,"free")
thisptr = 0
}
code_callptr = lpeek(ctx,168 + 48)//
if argmax>0{
dim clbk,57
clbk(0) = $83ec8b55,$45c730ec,$000000fc,$f845c700
clbk(4) = $00000000,$00e045c7,$c7000000,$0000e445
clbk(8) = $45c70000,$000000ec,$d845c700,$00000000
clbk(12) = $8bd84d89,$e0c1f845,$4d8b5002,$83d1ffe0
clbk(16) = $458904c4,$f445c7d4,$00000000,$00dc45c7
clbk(20) = $c7000000,$0000f045,$45c70000,$000000e8
clbk(24) = $0c558d00,$8be85589,$4d8bd445,$c7088908
clbk(28) = $0001d045,$09eb0000,$83d0558b,$558901c2
clbk(32) = $f8458bd0,$7dd04539,$e84d8b1a,$8904c183
clbk(36) = $558be84d,$d4458bd0,$8be84d8b,$0c89fc49
clbk(40) = $8bd5eb90,$458bf455,$8b0289f8,$558bdc4d
clbk(44) = $681189d4,$00000000,$ffec458b,$04c483d0
clbk(48) = $8bf04d8b,$fc558911,$00e845c7,$8b000000
clbk(52) = $8b50d445,$d1ffe44d,$8b04c483,$e58bfc45
clbk(56) = $0000c25d
lpoke clbk,$10,argmax:lpoke clbk,$17,ptrtomalloc:lpoke clbk,$1e,ptrtofree
lpoke clbk,$25,code_callptr:lpoke clbk,$2c,varptr(thisptr)
lpoke clbk,$48,varptr(ctx) + 36:lpoke clbk,$4f,varptr(ctx) + 40
lpoke clbk,$56,varptr(ctx) + 784:lpoke clbk,$b4,ilb
if ((mode & $f) == CLBKMODE_CDECL) == 0:wpoke clbk,$e2,argmax & $ffff
funcsize = 228
}
if argmax==0{
dim clbk,25
clbk(0) = $83ec8b55,$45c718ec,$000000fc,$f045c700
clbk(4) = $00000000,$00f845c7,$c7000000,$0000e845
clbk(8) = $45c70000,$000000f4,$ec45c700,$00000000
clbk(12) = $8bec4d89,$00c7f845,$00000000,$c7e84d8b
clbk(16) = $00000001,$00006800,$558b0000,$83d2fff0
clbk(20) = $458b04c4,$89088bf4,$458bfc4d,$5de58bfc
clbk(24) = $000000c3
lpoke clbk,$10,code_callptr:lpoke clbk,$17,varptr(ctx) + 36
lpoke clbk,$1e,varptr(ctx) + 40:lpoke clbk,$25,varptr(ctx) + 784
lpoke clbk,$2c,varptr(thisptr):lpoke clbk,$46,ilb
funcsize = 100
}
clbkptr = malloc(funcsize)
dupptr clbkfunc,clbkptr,funcsize,4
memcpy clbkfunc,clbk,funcsize
VirtualProtect clbkfunc,funcsize,$40,_x
ptrtable(ptrmax) = clbkptr
ptrmax++
return clbkptr
#defcfunc clbk_getthisptr
//Thisポインタを取得する。
//コールバックとして呼び出された直後に別変数へコピーしなければならない。
return thisptr
#deffunc modclbk_term onexit
repeat ptrmax
free ptrtable(cnt)
loop
if inited{
FreeLibrary hcrt
}
ptrmax = 0
return
#global
#endif
また、バグ等ありましたらお知らせください。
| |
|
2015/4/25(Sat) 01:20:03|NO.68741
・HSPのバージョンは3.4、使用OSはWindowsVista32bitです
・メモリが足りているかの確認方法が分かりません。タスクマネージャーで確認する限りメモリの大きな変動は確認されません
・モジュールは書き換わってはいません
以下のように使用しました
http://hsp.tv/play/pforum.php?mode=all&num=68455#68501
上記モジュール内のSortItem命令にて、リストビューのソートに使用するLVM_SORTITEMSEXメッセージからコールバック関数を呼び出しています
コールバック用モジュール、上記のモジュール、上記のスレッドの先頭のソースの順につなげ、stopの前に「AutoSort listviewID」と一行追加しました
私の環境では_MODCLBK3A1_ASでは動作するものの、_MODCLBK3B1_ASと_MODCLBK3B2_ASは「システムエラーが発生しました」と強制終了します
logmesをサブルーチンに挿入したところ、一回目は呼び出しに成功していますが、その次は引数を取得できずに終了しました
ただし、_MODCLBK3A1_ASの文末に付属のEnumWindows関数を使用したサンプルで試したところ、_MODCLBK3B1_ASと_MODCLBK3B2_ASのどちらも正常に動作しています
コールバック関数の呼び出し方法が間違っているのでしょうか?
|
|
2015/4/25(Sat) 22:00:50|NO.68768
以下の通り更新いたします。
これにより、一部の関数で無条件にシステムエラーが発生するバグが修正されます。
#ifndef _MODCLBK3B2_AS
#ifdef _MODCLBK3A1_AS
#undef _MODCLBK3A1_AS
#undef newclbk3
#undef clbkargprotect
#undef CLBKMODE_CDECL
#undef _newclbk3
#undef modclbk_term
#endif
#ifdef _MODCLBK3B2_AS
#undef clbk_getthisptr
#endif
#define global _MODCLBK3A1_AS
#define global _MODCLBK3B1_AS
#define global _MODCLBK3B2_AS
#define global _MODCLBK3B3_AS
#define global newclbk3(%1,%2 = 0,%3,%4 = 0) tmpclbklb@modclbk3b3=%3:%1=_newclbk3(%2,tmpclbklb@modclbk3b3,%4)
//新しい関数ポインタを取得する
// %1...関数ポインタを受け取る変数
// %2...引数の数
// %3...呼び出されるラベル
// %4...作成のモード(CLBKMODE)
#define global clbkargprotect(%1) lp@modclbk3b3=lparam:wp@modclbk3b3=wparam:dupptr args@modclbk3b3,lp@modclbk3b3,wp@modclbk3b3*4,4:dim %1,wp@modclbk3b3:memcpy %1,args@modclbk3b3,wp@modclbk3b3*4
//引数を取得する
// %1...引数を受け取るための変数
#module "modclbk3b2"
#define ctype uintbitshiftright(%1,%2) (((%1&$7fffffff)>>%2)|((1&(%1>>31))<<(31-%2)))
#uselib "msvcrt.dll"
#cfunc malloc "malloc" int
#func free "free" int
#uselib "kernel32.dll"
#func VirtualProtect "VirtualProtect" var,int,int,var
#cfunc LoadLibrary "LoadLibraryA" sptr
#cfunc GetProcAddress "GetProcAddress" int,sptr
#func FreeLibrary "FreeLibrary" int
#define global CLBKMODE_CDECL $00000001
// 呼び出し規約をcdeclに設定する
// 呼び出し規約をthiscallに設定する
#defcfunc _newclbk3 int _argmax,var clbklb,int mode
// int _argmax ... 関数の引数の数
// var clbklb ... 呼び出すサブルーチンが入った変数
// int mode ... コールバック関数のモード(CLBKMODE_)
dim _x,1
mref ctx,68
ilb=0
memcpy ilb,clbklb,4,0,0
argmax = _argmax
if inited == 0{
inited = 1
dim ptrtable
ptrmax = 0
hcrt = LoadLibrary("msvcrt.dll")
ptrtomalloc = GetProcAddress(hcrt,"malloc")
ptrtofree = GetProcAddress(hcrt,"free")
thisptr = 0
}
code_callptr = lpeek(ctx,168 + 48)//
if argmax>0{
dialog "argmax>0"
dim clbk,57
clbk(0) = $83ec8b55,$45c730ec,$000000fc,$f845c700
clbk(4) = $00000000,$00e045c7,$c7000000,$0000e445
clbk(8) = $45c70000,$000000ec,$d845c700,$00000000
clbk(12) = $8bd84d89,$e0c1f845,$4d8b5002,$83d1ffe0
clbk(16) = $458904c4,$f445c7d4,$00000000,$00dc45c7
clbk(20) = $c7000000,$0000f045,$45c70000,$000000e8
clbk(24) = $0c558d00,$8be85589,$4d8bd445,$c7088908
clbk(28) = $0001d045,$09eb0000,$83d0558b,$558901c2
clbk(32) = $f8458bd0,$7dd04539,$e84d8b1a,$8904c183
clbk(36) = $558be84d,$d4458bd0,$8be84d8b,$0c89fc49
clbk(40) = $8bd5eb90,$458bf455,$8b0289f8,$558bdc4d
clbk(44) = $681189d4,$00000000,$ffec458b,$04c483d0
clbk(48) = $8bf04d8b,$fc558911,$00e845c7,$8b000000
clbk(52) = $8b50d445,$d1ffe44d,$8b04c483,$e58bfc45
clbk(56) = $0000c25d
lpoke clbk,$10,argmax:lpoke clbk,$17,ptrtomalloc:lpoke clbk,$1e,ptrtofree
lpoke clbk,$25,code_callptr:lpoke clbk,$2c,varptr(thisptr)
lpoke clbk,$48,varptr(ctx) + 36:lpoke clbk,$4f,varptr(ctx) + 40
lpoke clbk,$56,varptr(ctx) + 784:lpoke clbk,$b4,ilb
if ((mode & $f) == CLBKMODE_CDECL) == 0:wpoke clbk,$e2,(argmax * 4) & $ffff
funcsize = 228
}
if argmax==0{
dim clbk,25
clbk(0) = $83ec8b55,$45c718ec,$000000fc,$f045c700
clbk(4) = $00000000,$00f845c7,$c7000000,$0000e845
clbk(8) = $45c70000,$000000f4,$ec45c700,$00000000
clbk(12) = $8bec4d89,$00c7f845,$00000000,$c7e84d8b
clbk(16) = $00000001,$00006800,$558b0000,$83d2fff0
clbk(20) = $458b04c4,$89088bf4,$458bfc4d,$5de58bfc
clbk(24) = $000000c3
lpoke clbk,$10,code_callptr:lpoke clbk,$17,varptr(ctx) + 36
lpoke clbk,$1e,varptr(ctx) + 40:lpoke clbk,$25,varptr(ctx) + 784
lpoke clbk,$2c,varptr(thisptr):lpoke clbk,$46,ilb
funcsize = 100
}
clbkptr = malloc(funcsize)
dupptr clbkfunc,clbkptr,funcsize,4
memcpy clbkfunc,clbk,funcsize
VirtualProtect clbkfunc,funcsize,$40,_x
ptrtable(ptrmax) = clbkptr
ptrmax++
return clbkptr
#defcfunc clbk_getthisptr
//Thisポインタを取得する。
//コールバックとして呼び出された直後に別変数へコピーしなければならない。
return thisptr
#deffunc modclbk_term onexit
repeat ptrmax
free ptrtable(cnt)
loop
if inited{
FreeLibrary hcrt
}
ptrmax = 0
return
#global
#endif
これでどうでしょうか。
他にも問題があれば教えていただけるとありがたいです。
このページにも多くのモジュールが投稿されているので、
「このページのモジュールを使ってください」
というときには、どの投稿のモジュール化わかるように書いていただけると
混乱が避けられると思います。
このモジュールのバージョンの見方について説明します。
ヘッダの最上部に
#ifndef _MODCLBK○△□_AS
と書かれていますが、
○の部分が変更されている場合は、
「使用方法に変更が出ていて、同じスクリプトは動きません。」
△の部分が変更されている場合は、
「命令などの機能が追加されています。
aに対してbならスクリプト上での互換があります。
できるだけアルファベット順に遅い方のモジュールを使ってください。」
□の部分が変更されている場合は、
「実装方法に変更がありますが、全く同じように使用できます。
できるだけ数字の大きいモジュールを使ってください。」
です。
今後もよろしくお願い致します。
※誤字をいくつか見つけたため再投稿いたしました。
| |
|
2015/4/27(Mon) 21:11:34|NO.68817
>(デバッグ用? のダイアログ表示行が残っていましたが)
ありがとうございます。
引数数0でのみテストをしていたらこんなことになってしまいました。
確かにデバッグ用です。
なるべく手動の書き換えなしで使えるようにしたかったのですが、
この長文を再投稿する大げささとパラドクスが気になったので、
あとから訂正いたします。
if argmax>0{
のあとにある
dialogの行は削除してください。
すみませんでした。
>モジュールを使用してサブクラス化も行っています
すでに様々な改造や活用が行われているようで嬉しいです。
皆さん、ありがとうございます。
|
|
2015/7/1(Wed) 16:34:19|NO.69919
もしよろしければ、このマシン語コードをどうやって生成したか教えていただけませんか。参考にした資料があれば、それも教えていただけると嬉しいです。
|
|
2015/7/1(Wed) 17:51:02|NO.69922
|
|
2015/7/2(Thu) 18:35:19|NO.69934
近々このモジュールを利用したモジュールを作る予定でいるんですが、
このモジュールってどうやって使うんですか?
なんか使い方を説明しているサイトも見当たらないので使い方もわからず…。
参考サイトでも構いません。
|
|
2015/7/4(Sat) 23:33:08|NO.69958
訂正です。
最後に投稿したスクリプトの
// 呼び出し規約をcdeclに設定する
のあとにある
// 呼び出し規約をthiscallに設定する
は不要です。
通常はthiscall(clbk_getthisptrを呼ばなければstdcall)で、
CLBKMODE_CDECL定数を指定した時のみcdeclになります。
また、注意点ですが、バージョン3b2は複数存在するのでご注意ください。
modclbkでyahoo検索するとワンキーヘルプが付加されたバージョンも見つかります。
公開者さんありがとうございます。
>どうやって生成したか
Cのソースから、
VisualStudioでcodファイルを生成して、
その中の機械語を4バイトずつ数値配列へ手入力して、
再配置が必要な部分を見つけてpoke系命令で再配置します。
40分位16進数とにらめっこして、
一つの関数を打ち終えて、
デバッグして、
システムエラーで最初から…。
とても楽しいですよ。
おすすめです。
>参考にした資料
http://chokuto.ifdef.jp/
http://chokuto.ifdef.jp/urawaza/mcn/index.html
など、他無数にありますが、忘れました。
>このモジュールってどうやって使うんですか?
No.66878にサンプルがありますので参考にしてください。
しかし、自分のプロセス外には使用できませんのでご注意ください。
|
|
2015/7/13(Mon) 17:53:33|NO.70105
もしよろしければ機械語の変換前のCのソースをもらえないでしょうか?
|
|
2015/7/13(Mon) 18:00:35|NO.70106
参考にしたいので。
|
|
2015/7/13(Mon) 20:55:05|NO.70109
>もしよろしければ
よろしくありません。
大昔に書いたコードであるため、
私の現在の書き方との好みが異なり、
恥ずかしいので現時点では公開いたしません。
どうしても公開して欲しければ、
その気になるようなことをしてください。
時間が経てば公開するかもしれません。
参考ではなくGPLで配布するためにどうしても必要だというのなら、
検討いたします。
しかし、元のCソースの3〜5割ほどは、
マシン語で打ち込むときに改変していますので、
Cソースは参考程度であり、
マシン語配列がソースと理解していただければうれしいです。
「HSPのスクリプトが挟まっているせいで単純な逆コンパイルができない」
という方のために、配列は配列に分離したつもりなので、
必要ならば逆コンパイルなり逆アセンブルなりしてください。
それは自由です。
|
|
2015/7/13(Mon) 22:49:30|NO.70111
そうですかわかりました。。
僕が思ったのは、コールバックということで
おそらく関数の定義にstdcallをつけていると考えられるので、
それをdllexportなどに変えて、dllmain関数を機械語に変換したのを
メモリに配置すればhspからdllが作れるのではないかと思ったからです。
需要があるかで言えばもし成功しても需要はないと思いますが、
かつてこの掲示板でも何回も話題になっていますし、
試みとしては面白いかなと思っています。
足らぬ頭で考えたことなのでトンチンカンなところがあるかも知れませんが、
そういうわけで、協力をお願いできないでしょうがか?
|
|
2015/9/23(Wed) 21:59:50|NO.71884
> おそらく関数の定義にstdcallをつけていると考えられるので、
> それをdllexportなどに変えて、dllmain関数を機械語に変換したのを
呼び出し規約で機械語に影響するstdcallと違って、dllexportは出力されるDLLのエクスポートテーブルに関数を登録する必要があります。
ですのでas側やhsp3ランタイム側での対応は出来ず、hspcmpのタイミングでの変更が必要になってMODCLBK.ASの改変というのは無理筋だと思います。
このエクスポートテーブルの作成方法としてtds12さんのSusieプラグインDLLで作成ではC++側でSusieに必要な関数を予めすべてエクスポートしていて、そこからhsp3.exe相当インタープリタ機能を呼び出しています。
他のソフトのプラグインを作りたい時も個別にhsp3spi.hrt相当のものを作成すれば対応可能です。
私のhsp3cnv-dllは方向性が違ってAndroidやiOSのdishと同じ用に一旦axをc++に変換してからVCで実行ファイルを作ることで、個別にhrt作成無し任意の関数をエクスポートすることを目指した実験です。
とりあえず↑のリンク先の物の test.hsp -hspcmp-> test.ax -hsp3cnv-> test.cpp -VC++-> test.dll とコンパイルして test.hsp から呼び出すところまでは出来てます。
HSPとCの違いで
* exportする関数指定をHSP側でどうやるか
* axでは関数名が全部小文字になる
* axからは関数の戻り値の型がわからない
というあたりは何らかの定義ファイルをhsp3cnvに渡す必要ありそうです
他の課題として次のようなのがありますが解決策思いついていません。
* 引数をどうHSP側に見せるか。特に構造体やコールバック
* 複数スレッドからDLLが呼ばれた時にどうするか
* (hsp3cnvを経由するので)dish相当の制限あるのは実用的か
誰か頑張ってください。
|
|
2015/9/23(Wed) 23:24:00|NO.71885
>HSPとCの違いで
>* exportする関数指定をHSP側でどうやるか
>* axでは関数名が全部小文字になる
>* axからは関数の戻り値の型がわからない
> というあたりは何らかの定義ファイルをhsp3cnvに渡す必要ありそうです
定義ファイルを作らなくても、hspファイル内に定義(宣言)を書けばよいと思います。
//hspファイル
#regcmd 18
//ランタイムのtype18に
#cmd dllexport $000
//DLLのExport用コマンドを登録して
//dllの関数定義
#module
//extern "C" int _export PASCAL GetPictureInfo(
//LPSTR buf,long len,unsigned int flag,struct PictureInfo *lpInfo);
#deffunc GetPictureInfo str buf,int len,int flag,int lpInfo
//LPSTRはstr,longはint,unsigned intはintを使い自力でunsignedとして扱う,
//構造体へのポインタはint型として受け取りdupptrする
return 0
#global
dllexport "stdcall","GetPictureInfo","int",4,"str","int","int","int":GetPictureInfo
//dllexport 呼び出し規約,エクスポート名,返値型名,引数数,引数型名n...:呼び出される命令
//というように指定する
>他の課題として次のようなのがありますが解決策思いついていません。
>* 引数をどうHSP側に見せるか。特に構造体やコールバック
構造体はポインタ渡しに限りint型でdupptr
コールバックはint型でcallfuncでよいと思います。
>* 複数スレッドからDLLが呼ばれた時にどうするか
単に、実行中のフラグをグローバルで作り、
関数の入り口でフラグを立てて、関数の出口でフラグを下すと決め、
フラグが下りるまで関数の入り口で空ループするというのでは、
甘いでしょうか。
>* (hsp3cnvを経由するので)dish相当の制限あるのは実用的か
結局VisualStudioを使うのなら、axファイルをもとに、
専用の実行ランタイムを自動生成するというのは、どうでしょうか。
| |
|
2015/9/24(Thu) 00:04:17|NO.71886
意外にも多くの人に返事を頂き、驚きを隠せません。
やはり、足らぬ頭で考えたのだと、穴がかなりあるようです。
ひとまず、今のところ、考えられる方法は、
1.専用のランタイムを作る
2.独自プログラムでAXファイルから変換する
の2通りだと理解しました。
どっちにしろ、
hspとcの違いをどのように補うのかが論点だと思います。
そこで、考えたのは、
モジュールで定義した関数をエクスポートするより、
専用命令を用意した方が、やりやすいのではないか、
と思いました。hspのモジュール作成機能と全く同じ使い方をするように頑張って
作れば、使い方に困ることはないと思います。
|
|
2015/9/24(Thu) 09:43:02|NO.71893
> 定義ファイルを作らなくても、hspファイル内に定義(宣言)を書けばよいと思います。
実行時には何もせず変換時に特別扱いする「命令」というのは私も考えたんですが、ぱっとみ命令に見えるので紛らわしいかなと。
// 実行時にならないと決定出来ないリテラル以外の引数は対応出来ない
dllexport "stdcall","GetPictureInfo"+a,"int",4,t,"int","int","int":GetPictureInfo
// 制御構文に対応出来ない
if flg {
dllexport "stdcall","GetPictureInfoA","int",4,"int","int","int","int":GetPictureInfo
} else {
dllexport "stdcall","GetPictureInfoW","int","int","int","int","int":GetPictureInfo
}
> 構造体はポインタ渡しに限りint型でdupptr
> コールバックはint型でcallfuncでよいと思います。
そのくらいが落とし所ですね。COMのように特別扱い出来ると便利ですが辛い…
> 単に、実行中のフラグをグローバルで作り、
DLL全体にロックをかけるのは一番単純である程度のケースには対応できる案ですね。
スピンロックをグローバル変数使って自分で正しく作るのは大変なのでmutex使うのがよさそうです。
あとは並列度上がりますが順に対応難しくなるのが
- wait/awaitしてる時はロックを解除して実行スレッド数は1のマルチスレッド対応
- コンテキストを構造体に包んで実行スレッド数Nのマルチスレッド対応
>* (hsp3cnvを経由するので)dish相当の制限あるのは実用的か
> 結局VisualStudioを使うのなら、axファイルをもとに、
> 専用の実行ランタイムを自動生成するというのは、どうでしょうか。
なるほど、そのほうが良さそうですね。
当初LLVM組み込んで直接DLL出力考えてました。
> hspのモジュール作成機能と全く同じ使い方をするように頑張って
> 作れば、使い方に困ることはないと思います。
頑張れるならその方法がベストだと思います。私やtds12さんの方策は(処理系の)実装コストを抑えつつDLLを作るなので…
| |
|