LoginSignup
0
0

JuliaでCのcharをStringに変換する方法

Last updated at Posted at 2023-07-21

備忘録的に。

JuliaでCのcharをStringに変換したい

JuliaでSDL2(SimpleDirectMediaLayer.jl)の文字入力を扱う機会があったのですが、文字の出力が、text=(-29, -127, -103, -29, -126, -126, -29, -126, -126, -29, -126, -126, -29, -126, -126, -29, -126, -126, -29, -126, -126, -29, -126, -126, -29, -126, -126, -29, -127, -82, 0, 127)みたいにNTuple{32, Cchar}型を取るために詰まってしまいました。

Ccharというのは、緩く言えば、1文字を数値の表現で表したunsigned intの8bitのデータで、JuliaにおいてもCと同じく数値表現として扱われます。

SimpleDirectMediaLayer.jlでは要するにccallなどで得られるC言語の出力をCcharのタプルとして返しているのですが、これをそのままprintlnったり、TTF_RenderUTF8_Blendedったりすると、「それ数字じゃね」ってJuliaは解釈する訳です。

解決までのロードマップ

僕はまずこの表現がもしかしたらJuliaだと良くあることなのかと思って、このタプル表現の文字列を直接Stringに突っ込んでみて反応を見てみる訳です。

text = Cchar.((-29, -127, -103, -29, -126, -126, -29, -126, -126, -29, -126, -126, -29, -126, -126, -29, -126, -126, -29, -126, -126, -29, -126, -126, -29, -126, -126, -29, -127, -82, 0, 127))
String(text)

しかし、結果は残念ながら失敗。そんな関数は知らぬとJuliaは返す訳です。

次に、C言語のcharの扱いを思い出そうと努力しますが……高専の頃の、もう随分前の知識で、思い出しても極めてあやふやです。

観念していろいろと調べてみて、やっとまともに動作するっぽいものが完成しました。同じ処理を万が一別の場所で呼び出すときに困らないようにBase.Stringにdispatchしてます。(本当は別の型名をつけてやるべきなんだと思いますが、現在の実装範囲では困らなそうなので、適当にdispatchしてます)

function Base.String(vec::NTuple{32, Cchar})
    ret = ""
    f = x -> (x < 0) ? 256 + x : x
    str = String(collect(UInt8.(f.(vec))))
    i = 1
    while (i <= 32) & isprint(str[i]) & isvalid(str[i])
        ret *= str[i]
        i = nextind(str, i)
    end
    return ret
end

text = Cchar.((-29, -127, -103, -29, -126, -126, -29, -126, -126, -29, -126, -126, -29, -126, -126, -29, -126, -126, -29, -126, -126, -29, -126, -126, -29, -126, -126, -29, -127, -82, 0, 127))

String(text) # "すももももももももの"

以上です。

0
0
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0