Programming」カテゴリーアーカイブ

g_fopen = int

#include <stdio.h>
#include <glib.h>
 
int
main (int argc, char *argv[]) {

    FILE*  f;

    /* OK */
    f = fopen("suzuki.txt", "w"); //return pointer
    fprintf(f, "SUZUKI %s", "Hayabusa");
    fclose(f);

    /* Error (x86_64) */
    f = g_fopen("kawasaki.txt", "w"); // return int
    g_fprintf(f, "KAWASAKI %s", "Ninja");
    g_close(f, NULL);

    /* No Error (x86_64)
    gint n = g_fopen("kawasaki.txt", "w"); // return int
    g_close(n, NULL); */

    return 0;
}

g_fopen

おいおい、どういうことだよ。
devhelp をよく見ると「コレは Windows の表記だ」とあるが。
fopen にマッピングではなく stat に合わせているのか?

glibc は glib のサブセットだと思いこんでいたけど違うんだな。
つまり Linux では FILE* は使わないほうがいいということみたい。
x86(32bit) だと気が付かないで混乱するかも。

glib – C言語で、UTF-8 の文字列から Unicode のコードポイントを取得するやりかた – Qiita

g_utf8_to_ucs4_fast って fast だから速いのかな?
GLib ってまだまだ知らないことが沢山あるな。

ただコードポイントを取得なら Python3 のほうが簡単そう。
単文字を ord() すれば UCS-4 のまま値が取れそうだけど、試すか。

文字コード考え方から理解するUnicodeとUTF-8の違い | ギークを目指して
「ほげふが」が [U+307B] [U+3052] [U+3075] [U+304C]
になれば OK ということね。

#!/usr/bin/env python3

s = "ほげふが"
for a in s:
    print("[U+{0:04X}] ".format(ord(a)), end=" ")

python_ord

思ったとおり。
ワイド文字が UTF-16 になる Windows 版じゃ変換が必要だけど。
ごめん Windows Python3 でも IronPython でもできるわ

win_code_point

ipy_code_point

Linux は GLib が簡単に使えて Python も実用的。
やはりプログラミングするなら Linux ですよ。

Dynamic array Length

GLib 関数で得た gchar** つまり文字列の配列の要素数。
ってよく考えたら Vala は foreach できるじゃないか。

/* valac -C test.vala */

class Test {
    public static int main(string[] args) {
        var l = Environment.list_variables();
        foreach (var s in l) {
            stdout.printf("%s\n", s);
        }
        return 0;
    }
}

g_get_environ のバインドが何故か無いので g_getenv バインドで。
コレがビルドできるということは Vala は要素数を得ているということ。
ということで毎度のように -C オプションしてチェック。

gint 
get_array_length (gchar** array) {
	gint length = 0;
	if (array)
	    while (array[length])
		    length++;
	return length;
}

これだけ?
配列がメモリ上でどうなっているか知っていれば確かに納得だけーが。
(char**) つかヒープ領域つか動的配列専用になってしまうな。

(char[ ][ ]) のスタック変数には絶対に使ってはいけない。
コッチはゴロゴロ見付かる方法で、と使い分けてください。
(char**) (char[ ][ ]) の両対応ははたして可能なのか?

とにかくテストコードを書いて確認。

#include <glib.h>

gint 
get_array_length (gchar** array) {
	gint length = 0;
	if (array)
	    while (array[length])
		    length++;
	return length;
}

gchar**
create_array(void) {
    gchar** arg;
    arg = (gchar**)g_malloc0(sizeof(gchar*) * 4);
    arg[0] = g_strdup("YAMAHA");
    arg[1] = g_strdup("HONDA");
    arg[2] = g_strdup("KAWASAKI");
    arg[3] = g_strdup("SUZUKI");
    return arg;
}

int
main (int argc, char *argv[]) {

    gchar** array;
    gint i, count;

    array = create_array();
    count = get_array_length(array);
    g_printf("count=%d\n", count);
    for (i=0; i<count; i++) {
        g_printf("%s\n", array[i]);
    }
    g_strfreev(array);

    return 0;
}

dynamic_array_length

上記は g_malloc0 でゼロ詰めしてセグメントエラーは一応回避している。
でも実際にアプリに使うとなると少し不安な感じ。

arg[2] = NULL;

等には完全に無力なわけで。
でもそれは配列を作る側の問題。

確実にいえるのは GLib 関数の戻り値に使うかぎりはコレで問題ない。
自前動的配列に使う場合はチョッピリ注意しよう。

g_strjoinv

ヒープ上に配列を作ってそのポインタを sizeof() してもポインタサイズしか得られない。
だとすると char** が戻って来るこんな関数の場合はどうなるんだ?

#include <glib.h>

int
main (int argc, char *argv[]) {

    gchar** env_array;
    int i;
    long count;

    env_array = g_get_environ();
    count = sizeof(env_array) / sizeof(env_array[0]);
    g_printf("count = %ld\n", count); //=> count = 1
    i = 0;
    for (i; i<count; i++)
        g_printf("%s\n", env_array[i]);
    g_strfreev(env_array);

    return 0;
}

だよね、両方 8byte になるから 1 という結果に。
手段は無いかな、検索検索。
動的にメモリを確保した配列の要素数を調べるには 【OKWave】
自作配列なら自分で管理すればいいけど関数で戻って来るのはお手上げか。

Python なら list で得られるから単純にループでイケるのだが。

python_env

まてよ、上記のように全部出力する場合なら Python の

"\n".join(env_arraya)

みたくできれば問題なくね?

#include <glib.h>

int
main (int argc, char *argv[]) {

    gchar** env_array;
    gchar* s;

    env_array = g_get_environ();
    s = g_strjoinv("\n", env_array);
    g_printf(s);
    g_free(s);
    g_strfreev(env_array);

    return 0;
}

strjoinv

こんなにアッサリ。
Python の join をバカにしている人、GLib ならむしろ自然だぞ。
破棄は g_strfreev に全部おまかせできるようです。

単純に全部くっつけるだけならコレでいいけど加工になると…
GList や GArray に変換は自力でやるしかなさそう。

GLib を使っても C 言語で文字列を扱うのは面倒臭いのは変わらない。
楽したけりゃ Python や Vala を、という結論で。

sizeof

sizeof ってスタック領域でのサイズだったのか!

#include <glib.h>
#include <stdio.h>

int
main (int argc, char *argv[]) {

    gchar* s;

    /* コレはイケる */
    gchar c[] = "たのしい Linux 1";
    g_printf ("%s は %ld 文字です\n", c, g_utf8_strlen(c, sizeof(c)));

    /* sizeof(s) が 8byte、つまりポインタのサイズになってしまう */
    s = g_strdup("たのしい Linux 2");
    g_printf ("%s は %ld 文字です\n", s, g_utf8_strlen(s, sizeof(s)));
    g_free(s);

    /* 一応試したけど同じだった */
    s = g_malloc(256);
    g_sprintf(s, "たのしい Linux 3");
    g_printf ("%s は %ld 文字です\n", s, g_utf8_strlen(s, sizeof((gchar*)s)));
    g_free(s);

    /* strlen ならイケるけど警告になる */
    s = g_strdup("たのしい Linux 4");
    g_printf ("%s は %ld 文字です\n", s, g_utf8_strlen(s, strlen(s)));
    g_free(s);

    /* Best */
    s = g_strdup("たのしい Linux 5");
    g_printf ("%s は %ld 文字です\n", s, g_utf8_strlen(s, -1));
    g_free(s);

    return 0;
}

sizeof

gcc でしか試していないけど、まあ思いっきり GLib だし。
(gchar*) キャストも無意味ってことはつまりそういうことだろう。
ひらがな UTF-8 は 3byte だから当然 2 文字分しか検出しない結果に。

検索しても何も見つからないのは何故だろう?
gcc 以外ならイケるのか、それとも皆スタック領域でしか sizeof を使わないのか。

てゆーかこの問題は -1 指定で普通に解決した。
おかげでこんなことが解ったので無駄な時間は結果オーライ。

GTK+ Inspector

海外の GTK+ 関連 Blog を見ていると GTK+ Inspector というものをよく見かける。
Projects/GTK+/Inspector – GNOME Wiki!
どうも Visual Studio 付属の spy++ のようなものみたい、実は何かよく知らなかった。
GPL ばかりの Linux ではソースを見ればいいのであまり興味も無かった。

が、今日なにげに Ctrl+Shift+I を押したら立ち上がってマジ驚いた!
キーボード設定を見てもそんな設定なんかしていないんですけど。
ちなみに Ctrl+Shift+D でもいい、Fedora ではデフォルトで使えるの?
てゆーか何故いままで気が付かなかったのだ?

もしかしたら gcc, gtk3-devel, gtk3-devel-doc が必要かもしれない。
GTK+ ヘッダとヘルプね、筆者は新規インストール直後にコレは入れるので。

使い方を検索してもやはり日本語情報は皆無か。
せっかくなので自分で少し使ってみよう。

とにかく GTK3 で作られているアプリを立ち上げ上記のキーを押す。
Python 製でも GTK3 ならいける、GTK2 の Firefox, Gimp はスルーされた。
Qt の KeepassX や独自 SDK の Libre Office でも当然立ち上がらない。
下記は Totem がアクティブ状態で Ctrl+Shift+I を押した状態。

gtk_inspector

OK ボタンで解析開始。
やはり spy++ みたいなものですがリアルタイムでプロパティを弄ることもできる。
たとえば Visual のタブでダークテーマの切り替えなんかも即時おこなえる。

カスタム CSS まで即時、ちなみに GTK+ Inspector 側にも適用される。
CSS で見た目の微調節をしたい場合なんかに凄く便利そう。

gtk_inspector_css

肝心の解析は左ペインで Widget の階層が解る、spy++ より判り易い。
本体から知りたい部分をクリックするとその Widget 部にフォーカスが移る。
初心者の頃他人のアプリを見て「こんなに積み上がってるの!」と驚いた。

他に Properties の Defined At が参考になるかな。
Totem 3.14 の動画表示部は GtkClutterEmbed をインプリメントしているね。
つーことは Clutter を使わない Ubuntu は次バージョンも古いアプリのままだなw

gtk_inspector_props

これ以上は各自で。
GTK+ でアプリを作る人以外は必要無いしさほど重要でもないアプリですけど。
せっかく Fedora なら即使えるので試してみるのもいいでしょう。