|
|
2014/9/12(Fri) 19:22:32|NO.64858
例えから
まず、このような命令を宣言したとします。
#deffunc HELLO str strin
mes strin+"Hello,World"
return
そして、これを
func = HELLO
func ,"TEST"
としたいです。
|
|
2014/9/12(Fri) 19:29:53|NO.64859
関数ポインタみたいなものでしょうか。
もし出来るのなら是非やりたいもんですが。
私は出来ないものとして認識しています。
|
|
2014/9/12(Fri) 19:57:17|NO.64861
HSPに可変長引数が実装されない限り変数に代入して使うことは出来ないと思います。
が、こんな実装でよろしければどうぞ。動作保証対象外。
// 魔法のコード(笑)
// スクリプトの先頭に入れておいてください
#define setfunc(%1,%2) dupptr a@funcloader,libptr(%1),28,2:dupptr b@funcloader,libptr(%2),28,2:memcpy a@funcloader,b@funcloader,28
if${
// 関数をここに並べます
#deffunc func
#deffunc func2
return
}
#module
#deffunc HELLO str strin
mes strin+"Hello,World"
return
#deffunc HELLO2 str strin
mes strin+"Hi guys!"
return
#global
setfunc func, HELLO
func "TEST"
setfunc func, HELLO2
func "TEST"
setfunc func2, func
func2 "TEST"
|
|
2014/9/12(Fri) 20:10:16|NO.64862
変数にこだわるなら(関数ポインタ的に使いたいなら)こちらを。
// 魔法のコード(笑)
// スクリプトの先頭に入れておいてください
#module funcloader
#deffunc callback
return
#deffunc local _flinit
dupptr a, libptr(callback), 28, 2
return
#define global loadfunc(%1) dupptr b@funcloader,%1,28,2:memcpy a@funcloader,b@funcloader,28
#global
_flinit@funcloader
// 関数を呼び出す側
#module
#deffunc cbtest int fnptr, int value
loadfunc fnptr
mes callback(value)
return
#global
// 関数が呼び出される側
#module
// 3倍した数値を返す関数
#defcfunc testfunc int val
return val * 3
#global
funcptr = libptr(testfunc)
cbtest funcptr, 123
|
|
2014/9/12(Fri) 21:44:44|NO.64868
nepisatさん
KOMARIさん
あとFlatさんへ
> 関数ポインタみたいなものでしょうか。
> もし出来るのなら是非やりたいもんですが。
> 私は出来ないものとして認識しています。
工夫次第で出来ると思います。
*Main
pfunc=*Jump3
HELLO "あいうえお"
stop
#deffunc HELLO str strin
gosub pfunc
return
*Jump1
HELLO1 strin
return
*Jump2
HELLO2 strin
return
*Jump3
HELLO3 strin
return
*Jump4
HELLO4 strin
return
#deffunc HELLO1 str strin
mes strin+"Hello1,World"
return
#deffunc HELLO2 str strin
mes strin+"Hello2,World"
return
#deffunc HELLO3 str strin
mes strin+"Hello3,World"
return
#deffunc HELLO4 str strin
mes strin+"Hello4,World"
return
↑
ラベル数はユーザ定義命令だけ増えますが、
C/C++のような関数ポインタみたいに使えます。
pfunc に *Jump2 を代入すると HELLO 命令で HELLO2 が実行されます。
この pfunc がユーザ定義命令を記憶してる変数ですね。
|
|
2014/9/12(Fri) 21:57:12|NO.64871
追記。
*Main
pfunc=*Jump3
HELLO "あいうえお"
stop
#deffunc HELLO str strin
gosub pfunc
return
*Jump1:HELLO1 strin:return
*Jump2:HELLO2 strin:return
*Jump3:HELLO3 strin:return
*Jump4:HELLO4 strin:return
#deffunc HELLO1 str strin
mes strin+"Hello1,World"
return
#deffunc HELLO2 str strin
mes strin+"Hello2,World"
return
#deffunc HELLO3 str strin
mes strin+"Hello3,World"
return
#deffunc HELLO4 str strin
mes strin+"Hello4,World"
return
↑
ラベル、命令実行、returnの3行を1行に出来るみたいです。
|
|
2014/9/12(Fri) 22:58:30|NO.64875
ミス。可変長引数なくても予め引数の数を指定できるのであれば先ほどの方法で使えます。黒魔術臭い方法ですが。
|
|
2014/9/13(Sat) 12:22:41|NO.64883
Flatさんすごい(・ω・)・・・
callbackの中身を無理やり書き換えてる感じなのはわかりました。
これは使えそうかも・・・
|
|
2014/9/13(Sat) 18:31:09|NO.64890
手元にPCがないのでわからないのですが、
1、 他の.hsp内で#deffunc (.hspの個数は可変)
2、 メインのスクリプトで すべての#deffuncを読み込む
3、 メインスクリプトで読み込まれた#deffncの名前を指定すると自動的に
それが実行されるようにする。
こういう処理ができるでしょうか?
|
|
2014/9/20(Sat) 14:20:41|NO.65080
すいません、質問の意図がわかりませんでした。
「#deffuncを読み込む」と「#deffncの名前を指定する」とは
どういったことを指すのでしょうか。
// a.hsp
#module
#deffunc abc
mes "xyz"
return
#global
// b.hsp
#module
#deffunc def
mes "123"
return
#global
// main.hsp
#include "a.hsp"
#include "b.hsp"
abc
def
|
|
2014/9/20(Sat) 14:44:12|NO.65082
#deffunc内に動作させる命令を入れればいいんじゃ((簡単すぎじゃい
でも一応方法を。
#deffunc Test
neturl "http://sampleurl.com/sample/"
mes "お待ちください..."
netload "1.html"
mes "完了"
return
|
|
2014/9/22(Mon) 18:24:44|NO.65132
わかりにくかったですね。
おそらくHSP標準についていないような気がします。
ファイルはMain.hspとIncludeフォルダにa.hsp b.hsp ....とあったとします。
まず、Includeフォルダ内は可変的にインクルードするファイルが増えたり減ったりします。
さらに、includeフォルダ内の.hspはすべて#deffuncです。
たとえば、
HELLO.hspといファイル内は
#deffunc HELLO
mes "HELLO"
return;
CLS.hsp内は
#deffunc CLS;
cls
return;
みたいな感じです。
あとは
Main.hspでincludeフォルダ内すべて読み込みして
ついでにファイル名も変数に代入、.hsp拡張子を切り捨てます。 (こうすると#deffuncの名前に)
ここからがわからないのですが、
変数に入れた関数名をそのまま呼び出せますか?
仮コード的なもの
//ロードしたファイル変数はdefinc
//ここでファイルロード(略します)
filenam = definc
//note命令でdefincを一行ごとに分割(略
//たとえばファイル名&deffncがHELLOの場合
if (cin(a) == definc.1){ //cinとは入力してaに代入 definc.1はdefincの一行目(HELLO)
filenam.1 (HELLO)
}
こんな感じです。
わかりにくいかも?
|
|
2014/9/22(Mon) 20:10:04|NO.65135
hspcmpは読み込んだスクリプト内で定義されている命令を直接呼べず、
GSは#deffuncのような命令定義に対応していません。
なので現状ではmistを使用するのが妥当かと思います。
http://dev.onionsoft.net/seed/info.ax?id=754
外部スクリプトをmstcompileで読み込み、
呼び出すときは関数名を文字列で指定する感じになります。
#include "mist.hsp"
mstinit
mstopenhsplib
sdim loadbuf
;bload "HELLO.hsp",loadbuf
loadbuf ={"
#deffunc HELLO
mes "HELLO"
return
"}
mstcompile loadbuf
mstcall "hello" // 小文字でないと呼び出しに失敗するらしい
stop
|
|
2014/9/22(Mon) 23:28:16|NO.65139
こんばんは。
黒魔術?正式な方法ではありませんが、#deffuncの命令を文字列で呼び出せる
モジュールを作ってみました。
▼ StrCmd.hsp
// HSP ver 3.32b にて確認。
// 文字列から#deffuncモジュール(仮) : 最初にインクルードしてください。
#ifndef StrCmd
#module StrCmd
#define global registerCommand(%1) registerCommandImpl libptr(%1)
/* 命令を「登録」する */
#deffunc registerCommandImpl int pStructDat
//-- 文字列を取得する
dupptr structDat, pStructDat, 28
nameidx = lpeek(structDat, 12)
dupptr funcNameBuf, mem_mds + nameidx, 64 //少し多めに
funcName = ""
repeat
char = peek(funcNameBuf, cnt)
if (char == 0) : break
funcName += strf("%c", char)
loop
//-- 登録
cmdFuncPtr(cmdCount) = pStructDat
cmdString(cmdCount) = funcName
cmdCount++
return
/* プレースホルダ */
#deffunc dummyCommand
/* 文字列を引数にして命令を呼び出す */
#deffunc callCommand str _cmd
cmd = _cmd
cmd = toLowerCase(strtrim(cmd, 0, ' '))
i = 0
repeat cmdCount
if (cmd == cmdString(i)) {
// 命令をコール
dupptr f_from, cmdFuncPtr(i), 28
dupptr f_to, libptr(DummyCommand), 28
memcpy f_to, f_from, 28
dummyCommand
break
}
i++
loop
if (i == cmdCount) {
// コマンドが見つからない(登録されていない)ときの警告
// とりあえず dialog を表示するようにしましたが、適宜変えてください。
dialog "コマンド '" + _cmd + "' が見つかりません"
}
return
/* 半角アルファベットを小文字にする */
#defcfunc toLowerCase str _string
string = _string
count = 0
repeat
char = peek(string, count)
if (char == 0 || count >= strlen(string)) : break
if (0 < char && char < 128) {
if ('A' <= char && char <= 'Z') {
poke string, count, (char + ('a' - 'A'))
}
count++
} else {
count += 2
}
loop
return string
/* 初期化 */
#deffunc local init
cmdCount = 0
cmdFuncPtr = 0
cmdString = ""
mref hspctx, 68
mem_mds = lpeek(hspctx, 12)
return
#global
init@StrCmd
#endif
このモジュールを使うには、#deffuncの命令を定義する.hspファイル内において、
その命令をregisterCommandで「登録」する必要があるので、その部分を書き加える必要があります。
具体的には、次のように書きます。(#moduleの内部にインクルードすると動きません)。
▼ test1.hsp
goto *@f
#deffunc Test1
mes "Test1が呼び出されました"
return
*@
// 命令を登録する
registerCommand Test1
▼ test2.hsp
goto *@f
#deffunc Test2
mes "Test2が呼び出されました"
return
*@
// 命令を登録する
registerCommand Test2
で、実際に使うには、最初にStrCmd.hspをインクルードしてから、
可変的にインクルードする.hspファイルをインクルードしてください。
callCommand "p1"
で、p1で指定した文字列に対応する#deffunc命令を呼びだそうとします。
▼例:main.hsp
// まず StrCmd.hsp をインクルードします。
#include "StrCmd.hsp"
// ここで可変的にインクルードするものをインクルードします。
#include "test1.hsp"
#include "test2.hsp"
// 文字列から↑で読み込んだ命令を呼び出してみる
callCommand "test1"
callCommand " TEST2 "
// 登録していない命令を呼び出してみる(警告)
callCommand "test100"
とりあえずここまでですが、こんなもので良ければ自己責任にてお使いください^^。

| |
|
2014/9/23(Tue) 09:10:55|NO.65146
>>nepisatさん
もしかしてコンパイル後にもincludeファイルが変わるような仕様にしたいのですか?
|
|
2014/9/23(Tue) 14:16:57|NO.65157
/*蛇足(ななしさんのスクリプトを整理して見た)*/
#module StrCmd
#define global registerCommand(%1) registerCommandImpl libptr(%1)
#deffunc registerCommandImpl int pStructDat
dupptr structDat ,pStructDat ,28
nameidx = lpeek(structDat, 12)
dupptr funcNameBuf,lpeek(hspctx,12)+nameidx,64
getstr funcName,funcNameBuf ;① 文字列の取得
cmdFuncPtr(cmdCount) = pStructDat
cmdString(cmdCount) = funcName
cmdCount++
return
#deffunc callCommand str _cmd
cmd = _cmd
cmd = getpath((strtrim(cmd,0,' ')),16) ;② 小文字化
repeat cmdCount
if (cmd == cmdString(cnt)) {i = 0
dupptr f_from,cmdFuncPtr(cnt) ,28
dupptr f_to ,cmdDummyPtr ,28
memcpy f_to ,f_from ,28
dummyCommand
break} :i = 1
loop
if (i) {mes _cmd + "が見つかりません"}
return
#deffunc dummyCommand
return
#deffunc local init
cmdCount = 0
cmdFuncPtr = 0
cmdString = ""
cmdDummyPtr = libptr(DummyCommand) ;③ ダミー関数ポインタ
mref hspctx, 68
return
#global
init@StrCmd
registerCommand Test1 ;④ ローカルジャンプ
registerCommand Test2
callCommand "test1"
callCommand " TEST2 "
callCommand "Test3"
stop
#deffunc Test1
mes "Test1が呼び出されました"
return
#deffunc Test2
mes "Test2が呼び出されました"
return

| |
|
2014/9/23(Tue) 14:49:53|NO.65159
.
http://hsp.tv/play/pforum.php?mode=all&num=64814
こいつで 定義ファイルを読み込み、
定義ファイルの拡張子抜きファイル名を読み込む。
string@mod0 = ""
exstring@mod0 = ""
draw
onkey *jump
stop
#module mod0
#deffunc draw
redraw 0
color : boxf // 黒で塗りつぶし
pos 0, 0
color 255,255,255
mes string
redraw 1
return
#deffunc keyInput int wp, int ip
switch wp
case 13 // Enter
string += "\n"
//文字列を実行する
excuteString exstring
exstring = ""
swbreak
case 8 // BackSpace
if (strmid(string, -1, 2) != "\n") {
string = strmid(string, 0, strlen(string)-1)
exstring = strmid(exstring, 0, strlen(exstring)-1)
}
swbreak
default // その他
string = string + strf("%c", ip)
// ↓実行する文字列を覚えておく
exstring = exstring + strf("%c",ip)
swbreak
swend
// 再描画する
draw
return
// 文字に合わせて実行
#deffunc excuteString str cmd
// たとえば...
switch cmd
case "読み込んだ定義ファイル名1"
読み込んだファイル名と同じ関数実行
swbreak
case "定義ファイル名2" // あいさつ
読み込んだファイル名と同じ関数実行
swbreak
case "ファイル名3" // 終了する
読み込んだファイル名と同じ関数実行
swbreak
swend
draw
return
#global
*jump
keyInput wparam, iparam
stop
↑で、読み込んだファイル名がHELLOで
HELLO.hsp内に
#deffnc
string += "HELLO"
と書かれていれば、
コマンド画面でHELLOと入力すると
HELLOと出るみたいなことがしたい。

| |
|
2014/9/23(Tue) 15:56:29|NO.65161
#module str_libptr
#deffunc local _initslibptr \
local hspctx, local hsphed
mref hspctx, 68
dupptr hsphed, hspctx(0), 96
dssize = hsphed(7)
dsptr = hspctx(3)
fiptr = hspctx(210)
finum = hsphed(15) / 28
return
#deffunc local getdsstr int offset, \
local statv, local data
mref statv, 64
if offset<0 || offset>=dssize {
statv = -1
return ""
}
dupptr data, dsptr+offset, dssize-offset, 2
statv = strlen(data)
return data
#defcfunc libptr_s str funcname, \
local finfo, local ptr, local found
ptr = fiptr
found = 0
repeat finum
dupptr finfo, ptr, 28
getdsstr@str_libptr finfo(3)
if stat >= 0 {
if getpath(refstr, 16) == getpath(funcname, 16) {
found = 1
break
}
}
ptr += 28
loop
if found == 0 : return -1
return ptr
#global
_initslibptr@str_libptr
libptr_s("関数名")で関数ポインタが得られるので、このモジュールと
http://hsp.tv/play/pforum.php?mode=all&num=64862
を組み合わせればできるかも。
|
|
2014/9/23(Tue) 16:34:34|NO.65162
忘れてましたがlibptr_sは全ての関数に対して動作します。
ユーザーが関数名を指定する場合はサニタイズを忘れないようにしてください。
|
|