ページ 11

dxlib4dで可変長配列の文字列をprintfDxで表示したい

Posted: 2012年7月24日(火) 05:08
by 大白定義
現在、D言語とSquirrelとDXライブラリを使って何か作ろうと考えています。
そこで、まずSquirrel側のprint関数の結果をDXライブラリのprintfDx関数を使って表示させてみようと思い、下のようなコードを書きました。

コード:

import std.stdio;
import std.stdarg;
import std.string;
import std.conv;

import squirrel;
import sqstdio;
import sqstdaux;

import dxlib;

extern(C) void PrintFunc(HSQUIRRELVM sq, const(SQChar)* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    
    //vfprintf(core.stdc.stdio.stdout, fmt, args);
    char[512] buf;
    vsprintf(buf.ptr, fmt, args);
    auto str = to!wstring(buf);
    printfDx(str.ptr);
    
    va_end(args);
}

void main(){
	ChangeWindowMode(TRUE);
	if(DxLib_Init() == -1) return;
	
	HSQUIRRELVM sqvm = sq_open(1024);
	
	sqstd_seterrorhandlers(sqvm);
	
	sq_setprintfunc(sqvm, &PrintFunc, &PrintFunc);
	
	sq_pushroottable(sqvm);
	
	if(SQ_FAILED(
			sqstd_dofile(
				sqvm,
				".\\script\\test.nut",
				SQFalse,
				SQTrue)
			)
		)
	{
		printfDx("スクリプト見つからへんで");
	}

	sq_close(sqvm);
	
	WaitKey();
	
	DxLib_End();
}
これはコンパイルには成功するのですが、実行すると
std.utf.UTFException@std\utf.d(645): Invalid UTF-8 sequence (at index 1)
という例外が発生してしまいます。

どのように解決すればよいのでしょうか?
ご教示のほど、よろしくお願いします。

コンパイラはDMD2.0、
ライブラリはdxlib4dと、SquirrelをDにインポートしたものを利用しています。

Re: dxlib4dで可変長配列の文字列をprintfDxで表示したい

Posted: 2012年7月24日(火) 08:59
by しひ
日本語を含んだソースコードをコンパイルする場合、ソースコードがUTF-8形式になっている必要があります。

Re: dxlib4dで可変長配列の文字列をprintfDxで表示したい

Posted: 2012年7月24日(火) 09:01
by しひ
ああ、コンパイルは成功しているんでしたね。
勘違いでした。

Re: dxlib4dで可変長配列の文字列をprintfDxで表示したい

Posted: 2012年7月24日(火) 09:14
by 大白定義
まず何かがおかしいと思ったら、printfDxに入れる引数を間違えていました。

そこでprintfunc関数を下のように書き換えました

コード:

extern(C) void PrintFunc(HSQUIRRELVM sq, const(SQChar)* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    
    //vfprintf(core.stdc.stdio.stdout, fmt, args);
    char[512] buf;
    vsprintf(buf.ptr, fmt, args);
    printfDx("%s", buf.ptr);
    
    va_end(args);
}
すると、実行時のエラー自体は解決しましたが、表示される文字列が文字化けしてしまいました。
printfDxをprintfに変更して実行すると文字化けしないようなのですが、これはDXライブラリがUTF-8に対応していないということなのでしょうか?

Re: dxlib4dで可変長配列の文字列をprintfDxで表示したい

Posted: 2012年7月24日(火) 13:10
by h2so5
DXライブラリの文字コードは通常だとShift-JIS, UnicodeモードだとUTF-16です。

Re: dxlib4dで可変長配列の文字列をprintfDxで表示したい

Posted: 2012年7月24日(火) 20:31
by 大白定義
h2so5さん、ありがとうございます。

UTF-16に変換するべく、std.utf.toUTFzで変換できないか試みてみましたが、するとまた
std.utf.UTFException@std\utf.d(645): Invalid UTF-8 sequence (at index 1)
というエラーが発生してしまいました。

ためしにprintfDx("テスト");として動くかどうかも試してみた所、問題なく表示されたので、dファイルそのものの文字コードが違う、ということも無いようです。

Re: dxlib4dで可変長配列の文字列をprintfDxで表示したい

Posted: 2012年7月25日(水) 00:59
by ISLe
SQCharってのはANSI文字列なんですかね。
vsprintfに書式文字列としてそのまま渡せる文字列なんでしょうか。

printfなら表示されるとありますけど、D言語のprintfということですかね。
そうするとvsprintfもD言語でUTF-8を扱うということですかね。

bufの内容を1バイトずつ16進数で表示してみたら何か分かる気がしますけど。

Re: dxlib4dで可変長配列の文字列をprintfDxで表示したい

Posted: 2012年7月25日(水) 01:02
by しひ
例外が出るのは、bufの空きが255で埋められているのが原因のようです。
char[512] buf = 0;として0で埋めた後、printfDx("%s", buf.toUTF16.ptr);として下さい。

それと、ファイルの形式はUTF-8, 16, 32のどれかであれば良かったみたいです。

Re: dxlib4dで可変長配列の文字列をprintfDxで表示したい

Posted: 2012年7月25日(水) 01:40
by 大白定義
>ISLeさん
基本的にD言語の標準ライブラリはC言語のものをラップする感じで作られているはずなので、C言語のprintf=D言語のprintfでいいと思います。

>しひさん
仰るとおりにやってみたところ、正常に動作しました!
ありがとうございます!

Re: dxlib4dで可変長配列の文字列をprintfDxで表示したい

Posted: 2012年7月25日(水) 02:36
by ISLe
未確認ですが、buf.toUTF16z.ptrにすると0で埋めなくても済むのではないでしょうか。
文法的に間違ってたらすみません。

Re: dxlib4dで可変長配列の文字列をprintfDxで表示したい

Posted: 2012年7月25日(水) 06:37
by 大白定義
いえ、確認してみたところ、bufを0で埋めておかないとエラーが発生しました。
0で埋めるのは必須のようです。

Re: dxlib4dで可変長配列の文字列をprintfDxで表示したい

Posted: 2012年7月25日(水) 17:29
by ISLe
buf.toUTF16.ptr

buf.toUTF16z.ptr
に変えたら終端文字までしか処理しないようになると思ったのですが。
z付きってそういう意味じゃなかったんですかね。

Re: dxlib4dで可変長配列の文字列をprintfDxで表示したい

Posted: 2012年7月25日(水) 22:30
by しひ
toUTF16とtoUTF16zの違いは、返される文字列の最後に終端文字が付くかどうかの違いです。
元々、D言語の文字列に終端文字は存在しないのでそのような区別は必要ないのですが、
C言語の関数を呼び出すときは最後に0を付加してやる必要があるので区別されています。