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

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 なら即使えるので試してみるのもいいでしょう。

GLib stdin

時は 2015 年

@ サイト管理者やプログラマー
今後は更にスマートフォンの時代になる、タッチパネル向けに作らなければ!

@ 絵師
ソシャゲ用イラストの需要が凄い、ソッチ向けを考慮しなきゃ!!

@ 一般的な人
モンストと Line で忙しい、おっと便利なサイト発見etc…

@ ネクラでキモチワルイ人達
スマホで充分という人はパソコンでもたいしたこと(以下略)ドャァ!!!

こうなることは解っていたがスピードが速すぎな気がする。
実際の話、仕事に必要という理由以外でパソコンを買う人は減る一方なのは確実。
筆者は Fedora 愛用だが実は他人には Mac かタブレットを勧めている。
Linux なんてサイトを自力で作っている人以外にはメリットが無いので。

確実なのは Windows は既にデファクトスタンダードでは無いということ。
モバイルでの Web に関してはもはや Safari がスタンダードに近い。

大型バイク乗りのオッサン、もういいかげんにビクスクを認めろよ。
確かに大型バイクはカッチョイイけどそんなものオイラ達には不要なんですよ。
PCX150 がバカ売れしている時点で余程のバカでなければ気が付くはずなのだが。
その「余程のバカ」が多すぎる、スマホ普及率をガン無視するネラー共と同じく。

絵に関しては Mac 使いにまかせる、その理由で Mac にしたはずだし。
こんな時代にパソコンを使うならプログラミングは必須。
でないとネクラでキモチワルイ人達の一人だと思われてしまう。

そんなこんなで GLib Tips のページを作ろうと思ったわけですが。
GLib って scanf, fgets, fgetc という標準入力のラッパーが無いんですね。

scanf は色々アレなので fgets を今迄使っていたのだが。
コレも色々ある、バッファオーバーランに無力だしスタック領域が無駄だし。
何より改行コード付随というのが気に入らない。

#include <stdio.h>
#include <string.h>
 
int
main (int argc, char *argv[]) {
    char line[256];
    printf("Hi!\nPlease enter your name: ");
    fgets(line, sizeof(line), stdin);
    /* Remove '\n' */
    line[strlen(line)-1] = '\0';
    printf("Welcome, %s!\n", line);
    return 0;
}

ライブラリ関数で取得したものを自力で再加工なんて無駄にもほどがある。
ならば最初から自力で取得し加工したほうが無駄がない。

/* valac -C src.vala */
stdout.printf ("Hi!\nPlease enter your name: ");
var name = stdin.read_line ();
stdout.printf ("Welcome, %s!\n", name);

Vala には stdin.read_line() という便利な関数がある。
コレをどう C 言語にジェネレートしているか -C オプションで確認。
なんと自前で関数を作って適用するという恐るべし手段を使っていた。
相変わらず最適化依存のナニコレなコードを出力するが省略するとこういうこと。

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

/* gcc src.c `pkg-config --cflags --libs glib-2.0` */

static gchar*
iostream_read_line (FILE* p) {

	GString* gstr;
	gchar* result;
    gint n;

	gstr = g_string_new("");
	while (TRUE) {
	    n = fgetc(p);
        if (n == ((gint)'\n') || n == EOF) {
			break;
		}
	    g_string_append_c(gstr, (gchar)n);
    }
    result = g_strdup(gstr->str);
    g_string_free(gstr, TRUE);
    return result;
}

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

    gchar* line;

    g_printf("Hi!\nPlease enter your name: ");
    line = iostream_read_line(stdin);
    g_printf("Welcome, %s!\n", line);
    g_free(line);

    return 0;
}

glib_iostream

fgetc で 1 byte ずつチェックしヒープ領域に積み立てて最後にポインタを戻す。
なるほど、これならスタック領域の無駄も最小限だしバッファオーバーランの心配も皆無。
日本語入力も半角スペースも何一つ問題なく処理できてしまう恐るべき関数であった。
Vala を作っている人達は想像以上に頭がいいようです。

ライブラリ関数に徹底的なほど拘るのも悪くないと思うんですけど。
強引に利用するより自分で関数を作ったほうが建設的だなと。
つか、ライブラリ関数に拘る人ってモレなく何もアプリを作っていない現実がね。

GtkFlowBox

開発者、システム管理者、ディストリビューター向けの新規事項

GTK+ 3.14 はマルチタッチをサポートしているのようです。
GtkGesture という名前か、マウスジェスチャはもう過去の遺物だな。

よし早速、ってタッチパネルのパソコンなんて持っていないよ。

後二年もすれば五万円台で ASER か ASUS が普通に出してくるのだろう。
コイツはそれからでいいや。

Gtk 3.12 のほうを見ると GtkActionBar, GtkPopover, GtkFlowBox
全部コンテナか、そんなに沢山の種類が必要なのかな?

GtkFlowBox はコンテナサイズで複数 Widget の位置を調節してくれる。
という解釈でいいのかな、GtkIconView とは違うのかな。
ちと試してみよう。

2015.03.05 修正

#!/usr/bin/env python3

from gi.repository import Gtk, Gio

class FBox(Gtk.Window):
    """
        Minimum width is standard ?
    """
    def __init__(self):
        Gtk.Window.__init__(self)
        # 
        self.flowbox = Gtk.FlowBox.new()
        button = Gtk.Button.new_with_label("Insert Label")
        button.connect("clicked", self.on_insert_button_clicked)
        # pack
        vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
        vbox.pack_start(button, False, False, 0)
        vbox.pack_start(self.flowbox, True, True, 0)
        # self
        self.index = 0
        self.add(vbox)
        self.connect("delete-event", Gtk.main_quit)
        self.resize(400, 1)
        self.show_all()

    def on_insert_button_clicked(self, widget):
        label = Gtk.Label("Label")
        label.show()
        self.flowbox.insert(label, self.index)
        self.index += 1

FBox()
Gtk.main()

gtkflowbox

3 クリック目から横に余裕があるのに縦に広がってしまう。
どうも横幅を最小値にした場合を常に計算しているようで。
ついでに、GtkListBox 同様に選択もできます。

どんな場面に便利か思いつかないのは筆者の想像力が足りないのだろう。
昨今の Web ページではよく見かけるのですけどね。