Home -> HSP講座 -> HPI編 No.05

文字列を使おう

HSPとプラグインの間で、文字列をやりとりします。
特別なことはしません。前回までの復習みたいなもんです。

今回のプラグインのソースコード:「strmul」リポジトリ


strmul()関数

「文字列×数値」で文字列を反復したいと思っている人も多いんじゃないかと思います。
Stringクラスを作るなら * 演算子を定義しますよね?
これを、関数で実現します。
つまりこんな感じ。

// strmul() テスト

	mes strmul( "STRING : ", 5 )
	// [output] STRING : STRING : STRING : STRING : STRING : 

手抜きだ……。


コーディング

プラグインの大半は前回と同じです。
cmd.cpp に書く、実体部分だけを書きましょう。

まずは、第一引数の文字列を受け取ります。
code_gets() でしたね。

待て
待て待て、おまえ前回と違うじゃねぇか。
命令は void strmul(void) で、関数は int strmul(void** ppResult) だったろう。

誰かに怒られてしまいました。
その通り、宣言がいつも通りではありません。
これは、命令形式関数形式両方に対応するための工夫です。
switch文の中で、命令にも関数にもなるようにコーディングします。( それは後で )

では続けましょう。

cmd.cpp : 非効率な実装

一気に全部書いてみました。特別難しいことはありませんので。
hspmalloc, hspexpand, hspfree は、関数 malloc, realloc, free とほぼ同じです。
計ったことはありませんが、64byte程度なら高速に動作するそうです。( hspdll.txt 参照 )

実装は hspsdk31/hsp3/ の strbuf にある、sbAlloc, sbExpand, sbFree 関数です。
strmul() 関数は、実装の都合上 hspfree( psResult ) としませんが、
hspmalloc した領域はHSPの終了時に解放されるので、メモリリークの心配はありません (いわゆる内部リークはします)


code_gets()の罠

というてほどではありませんが、注意点です。
code_gets()で取得した文字列へのポインタは、次に code_**() 系関数を使うと無効になります。
そのため strmul() では、一度 prmstr にコピーしています。
変数 ps のポインタは code_getdi(0) の時に無効になってしまうので。
※code_getds()でも同じ。

VC++の場合、ヘッダファイル <string> で std::string 型が使えるので、
それを使ってもかまいません。というか使った方が楽ですね。
メモリ管理は基本的にクラスに任せるべきですねー。


形式別の対応

switch文の中で、上記の関数を使用します。

命令形式の場合、結果をシステム変数 refstr に格納します。
refstr は ctx->refstr で、char* 型です。
ctx は HSPCTX構造体へのポインタで、HSPの実行中のあらゆる情報を持つ構造体です。
各種システム変数の値はここにあるので、hsp3struct.h でも覗いてみてください。

ちなみに、refstr の容量は HSPCTX_REFSTR_MAX バイトです。
strcpy() で領域破壊とかしないように気を付けて扱いましょう。

関数形式では、ProcFunc() に渡される ppResult に間接参照して、strmul() 関数の返値 (char*) をセットします。
そして、文字列型なので HSPVAR_FLAG_STR を返します。

問題ありませんね。
case の値は、命令の時と同じ 0x000 です。


ヘッダファイル

さて、恒例のヘッダファイルです。
いつも通り。

// strmul - public header

#ifndef IG_STRMUL_HPI_AS
#define IG_STRMUL_HPI_AS

#regcmd "_hsp3hpi_init@4", "strmul.hpi"
#cmd strmul 0x000

// サンプル・スクリプト
#if 1
	x = "strmul.hpi's sample!\n"
	
	mes strmul( "STRING : ", 5 )
	mes strmul( x, 2 )
	
	// 命令形式( refstr に格納 )
	strmul x, 4
	mes refstr
	stop
#endif

#endif

BCCの人は _hsp3hpi_init@4 を hsp3hpi_init に変えてください。

命令形式は必要なのか!?
というツッコミはナシです。


おわりに

今回は特に難しいことはしませんでした。
これが分からなければ、前回までをしっかり復習した方がいいでしょう。

では、また次回。


by 上大

第四章へ   第六章へ