C/C++」タグアーカイブ

y901w-0.0.0

Linux 飽きた。
Python もなんか気が乗らない、というか開発系 Blog が軒並み止まっているような…
時期的に .NET Framework 4 前というのもあるし C# 屋達もイマイチだね。

ならばしばらく Windows で C/C++ といこう、なんて久しぶりな。
せっかくだからずっと放置の Cinema の更新でも。
いやいや Y901w と名前を変えて Y901x にデザイン等を合わせるほうがいいと思う。
というより x64 対応ビルドを少しやってみたい。

問題は Visual Studio を VirtualBox 上の x86 Vista に入れていることだ。
x64 で debug できないし VMR9 が動かない、まぁビルドはできるからなんとかなるさ。

とりあえずファイルドロップで再生できるだけのスケルトンを Cinema から抜き出し。
抜き出したわりにはファイルがイッパイある、SDK だけで作るとこうなるんだよなぁ。
ということで x64 ビルドプロジェクトを含めてソースコードのバックアップ。

y901w-0.0.0.zip

x64 で再生できるか試してみる。
って Windows 7 64bit だと wmv 以外はドエリャァ面倒くさいのね。
ffdshow を入れて haali ってのを入れてやっと H.264 が再生できる。

Linux ならリポジトリからアッサリとデコーダーを導入できるのに…
つか WMP は標準で H.264 を再生できるのにサードには提供してくれないという…

普通に検索すると怪しさ全快なページばかり当たるので wikipedia から辿る。
そうだった、Windows でこの手は既に無法地帯化しているんだったよなぁ…
やっぱりヤメようか、まぁ x64 で DirectX の実験だと思えばいいか。

おぉ x64 ネイティブで普通に動いた。
後は部品を付けてチマチマやればなんとかなりそうだ。
ところで今頃気がついたのだが…

Opera って GStreamer 使っているの?
というか Windows から使えるのなら使ってみたいわな。

glade

覚書ページの整理が全然進まない。
PyGtk はどの順番で widget 解説を進めるか考えると頭がおかしくなりそう。
TreeView や TextView の前に Scrollbar や Scale の前に Adjustments の知識が必要で…

それより、もう使わなくなった Glade 関連の解説なんかはどうしようかと。
なんたって今では普通 libglade ではなく GtkBuilder を選ぶだろうし。
最初の GUI アプリ作りのとっかかりは Glade ほど解りやすいものは無いだろうし。

いやまてよ。
C 言語から Glade を使う方法てか GTK+ コンパイル方法も併記すればいいんでない。
なんたってソレは私自身もやったことがないので勉強にもなる。

よし Mandriva One に Glade や GTK+ ヘッダをインストールしてみよう。
C でやるには別途でコンパイラの他に GTK+ ヘッダを入れる必要があるんだよね。
Ubuntu での需要ばかりだろうから Ubuntu には後で入れる。

libgtk+2.0_0-devel を導入。
依存関係で他のパッケージも沢山インストールされるが気にしない。

devhelp も導入。
/usr/share/gtk-doc 以下の doc はコレで見られるようになる。
libgtk+ を入れた後はこんな感じになる。

glade も一応入れてと。
んで海外からチュートリアルを探してみたら強烈なとこを見つけた。

GTK+ and Glade3 GUI Programming Tutorial – Part 3

とにかく tutorial.xml を落とし C コードをコピペしてコンパイルしてみる。

普通にコンパイルが通って動かせた。
ふむふむ、C から Glade ファイルを使うにはこうすればいいのか。
しかしこんなトコを見た後では何を書くのも気後れするわ。

でもコンパイルオプションが長くてメンドクセ!
メモリの解放処理をいちいち書かなければいけないのがメンドクセ!
つーかメソッドではなく関数を使うのがメンドクセ!
PyGtk がどれほど楽チンなのか改めて思い知る。

C 言語で文字列メンドクサイ

最近の Linux なら locale は ja_JP.UTF-8 でイケるようだ。

scanf – Wikipedia
scanf ってこんなに面倒だったかなぁ…
gets だと思いっきり警告だし。

wchar_t って Linux では 4 バイトなんだね。
Windows つか Visual Studio では 2 バイトなのですけど。

最近の Windows SDK のようにセキュリティ関数が存在してくれないと怖いなぁ…
文字列処理って簡単にバッファオーバーランが起こせるからね。
malloc で動的処理すればなんとかなりそうだけど std::string のほうが(略

日本語の文字数カウントとかをするには UNICODE にするのが一番なわけで。
とりあえずバッファオーバーラン等を考慮しないでうまくいったコード。

#include <stdio.h>
#include <stddef.h>
#include <locale.h>
#include <string.h>

int 
main (int argc, char *argv[])
{
    /* set locale */
    setlocale( LC_CTYPE, "ja_JP.UTF-8" );

    /* おまけ、変数バイト数チェック */
    printf("int     サイズ = %d\n", sizeof(int));
    printf("char    サイズ = %d\n", sizeof(char));
    printf("wchar_t サイズ = %d\n", sizeof(wchar_t));

    /* バッファ */
    char cin[256];
    wchar_t s[256 * 4];
    char c[4] = {0};

    /* 何か入力させる */
    printf("何か文字列を入力して Enter\n");
    scanf("%s", cin);

    /* UNICODE に変換 */
    const char *cc = cin;
    size_t t = mbsrtowcs(s, &cc, strlen(cc), NULL);
    printf("文字数は %d です\n", t);

    /* 一文字ずつ書き出ししてみる */
    int i=0;
    for (i; i<t; i++)
    {
        wctomb(c, s[i]);
        printf("%s\n", c);
    }
    return 0;
}

あーくそ!Python ならたったコレだけ、import も無しで同じことができるんだが。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

s = raw_input("何か文字列を入力して Enter\n")
u = unicode(s, "utf8")
print "文字数は %d です" % len(u)
for c in u:
    print c.encode("utf8")

しかもバッファオーバーランの心配は無いと思うし。

※追記、GLib を使えば簡単だった
gunichar | PaePoi

クライアント領域のサイズ

GetWindowRect とか自分で書いて思い出したので書いておこう。
Windows の SDK を含む GUI ツールキットと Linux での GTK+ のサイズについて。
とりあえず全部 300×300 サイズなウインドウを作ってみる

SDK

hWnd = CreateWindow(
    szWindowClass,
    szTitle,
    WS_OVERLAPPEDWINDOW, 
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    300, // Width
    300, // Height
    NULL,
    NULL,
    hInstance,
    NULL);

WindowsForm

WPF

<Window x:Class="_wpf.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Grid>
        
    </Grid>
</Window>

PyGtk (Linux)

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import gtk

class Template(gtk.Window):
    def __init__(self):
        gtk.Window.__init__(self)
        self.connect("delete-event", gtk.main_quit)
        self.resize(300, 300)
        self.show_all()

if __name__ == "__main__":
    w = Template()
    gtk.main()

MFC や Qt は知らない、MFC は SDK と結果は同じになるはずだが。
とにかく結果、Windows の画像は VirtualBox ose 上である。

GTK+ はクライアント領域のサイズ、Windows は全部が全体サイズです。
いやいや、Windows は WPF になってもまだデフォルトは外枠を含んだサイズなんですね。
よく見るとメニューさえクライアント領域に食い込んで含まれてしまうのが解る。

Windows でクライアント領域のサイズを指定するには

SDK の場合
AdjustWindowRectEx 関数を使うか GetClientRect との差を自力計算する。

WindowsForm の場合

this.ClientSize = new Size(300, 300);

WPF の場合
SizeToContent を WidthAndHeight に指定し 300×300 のコンテンツを入れる。

何故クライアント領域のサイズがどうだというと。
メニューやツールバー、ステータスバーなんかも当然クライアント領域内に食い込む。
画像ビューアや動画プレイヤーを作る場合は当然実寸で表示したくなるよね。
そうするとメニューやステータスバーのサイズまで計算し加算しなくてはいけないハメに…
ちなみに私の作った Cinema はそうやっている、ステータスバーは面倒で付けなかった。

コンテンツのサイズでクライアント領域サイズを決めたほうがイイに決まっている。
本当に GTK+ や WPF のレイアウタって神ですよ。

SDK はしかたがないとして WindowsForm はどうなんだ?ですよね。
WPF は古い考え方をブチ壊したのだから最初からクライアントサイズにすればいいのに。

structure

ネタを何にしようか困っていたけどドコかの誰かにヒントをもらったので構造体を。

構造体は何気に便利です。
単純に「入れ物」として使うだけでもありがたい言語仕様である。

たとえば WindowsSDK には RECT 構造体が define されている。
RECT 構造体

コレを Linux で利用するには自身で定義するだけ。
LONG なんて Linux では当然定義されていないので int か long で全置換。

#include <stdio.h>
#include <string.h>

typedef struct tagRECT { 
    int left;
    int top;
    int right;
    int bottom;
} RECT;

int main(int argc, char *argv[])
{
    RECT rc = {10, 10, 320, 240};
    
    printf("x=%d, y=%d, width=%d, height=%d\n", rc.left, rc.top,
        rc.right - rc.left, rc.bottom - rc.top);
    return 0;
}

後はこの rc という変数の要素がウインドウのサイズ情報なのだと理解しやすい。
他のデータは他の構造体でまとめる、内部で利用する情報はまとめたほうが整理しやすい。
ソレのドコが便利なのかはメモリ内に保存するデータが多くなると実感するよ。
実際にアプリを作っているといつのまにかトンデモネェ数になってしまうから。

たとえば私の作った Y901x でのアトリビュートや Cinema の public 変数中身の数を見て呆れてくれ。
実際にアプリを作ったことが無い人には解らないかもだけどコレでも少ないほうだ。

それだけならたいして便利では無いのですけど。
Windows で GUI アプリを本当に作っている人なら GetWindowRect 関数を使ったことが無い人はいない。
と思うけどどうなのだろう。
GetWindowRect 関数

そう、この関数に RECT 構造体のポインタを渡せばウインドウ外観のサイズ情報は一度で取得できる。

void hoge(HWND hWnd)
{
    RECT rc;
	GetWindowRect(hWnd, &rc);
	/* サイズに関する何かの処理 */

つまり構造体のポインタを渡すだけで多数の情報を一度でゲットできる関数を作れば後々で楽。
C# 言語なんて仕様でソレを駆使している感じ、GC なので戻り値で済ませるように作っているけど。
おかげで型がアホみたく多い言語になってしまったのは何ともいえん、バランスって難しい。

とにかく、後々サイズ大きくなりそうなアプリを作るなら構造体の利用方法を覚えたほうがいい。
というか class の利用方法を覚えるのに必須の知識ですので。