About

地図会社で働いていたプログラマ。

2012年12月16日日曜日

はじめてのAndroidアプリ。

 

はじめてのAndroidアプリ。

思ったより簡単だったね!

Screenshot_2012-12-16-22-01-10

 

ソース

// MainActivity.java
package com.example.helloworld;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;
import android.widget.Button;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Button button = (Button)findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TextView text = (TextView)findViewById(R.id.textView1);
text.setText("Hi, This is the very first Android app of mine!");
}
});
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}


 



// res/layout/activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" />

<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="@string/textView1_text" />

<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView1"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"
android:text="@string/button1_text" />

</RelativeLayout>

2012年12月9日日曜日

[翻訳] 64ビット環境移植における20個の問題【途中】

翻訳元サイト
20 issues of porting C++ code on the 64-bit platform
http://www.viva64.com/en/a/0004/#ID0EMEBK

概要

C++コードを32ビットから64ビット環境へ移植する際に発生し得る問題について述べる。間違ったコードとそれを正す方法を示す。また、これらの問題を診断するコード解析手法についも述べる。

序論

本稿では、32ビットから64ビット環境へ移植手順について議論する。本稿はC++プログラマ向けであるが、別プラットフォームでアプリケーションを移植する全ての人に有用な情報となるかもしれな。著者は64ビット環境移植の専門家と64ビット移植に特化したコード解析ツールViva64ツールの開発者である。

64ビット移植をする際には、他の数千以上もあるプログラムの間違いではないの新しいタイプのエラーを理解するべきである。これらは全ての開発者が経験する不可避の問題である。この記事ではそのような問題に対する準備と対策方法を示す。プロミングだけでなく全ての新しい技術は、いくつかの制限や問題を抱えている。64ビットソフトウェア開発も状況は同じである。われわれは64ビットソフトウェアがIT開発の次のステップだと知っているが、実際はほとんどのプログラマは64ビットプログラム開発に関わっておらず、これらの問題に触れる機会はない。

64ビットアーキテクチャの利点を長々と話すつもりはない。このテーマに関してはたくさんの文献があるので参照されたい。この記事の目的は、64ビットアプリケーションの開発者が直面する問題の考察し、以下を学ぶことにある。
  • 64ビットシステムで起こる典型的な問題
  • それらの理由と対応するコード例
  • エラーの修正方法
  • 64ビットプログラムの間違いを探す方法

この知識によって読者は
  • 32/64ビットシステムの違いを理解できる
  • 64ビットプログラムを開発する際に間違いを避けられる
  • デバッグやテストにかける時間を減らせることで、32ビットから64ビットへの移植をすばやく行える
  • 移植にかかる時間をより正確に見積もることができる

また、この記事の中には多くのサンプルコードが含まれているため、より深く理解するためにぜひ試していただきたい。これは読者にとって64ビットの世界の入り口となるはずだ。まずは、以降の説明の手始めにいくつかの型を思い出してほしい。


整数型とメモリサイズ型
型名型のサイズ
(32ビット)
型のサイズ
(64ビット)
説明
ptrdiff_t3264ポインタの引き算時に使用する符号あり整数型。この型はメモリサイズを保持するのに利用するまた、関数の戻り値の型としてサイズやエラー時に-1を返す。
size_t3264符号なし整数型で、sizeof()等、オブジェクトのサイズや数を保持するのに使われる。
intptr_t, uintptr_t, SIZE_T, SSIZE_T, INT_PTR, DWORD_PTR, etc3264ポインタの値を保持する整数型。
time_t3264秒単位の時間。


この記事では、これらの型を”メモリサイズ型”と呼ぶことにする。この用語はポインタを保持し、プラットフォームが32から64ビットへ変わることによってサイズが変化する全ての型を意味する。たとえばメモリサイズ型として、size_t、ptrdiff_t、全てのポインタ、INT_PTR、DWORD_PTR等がある。


32/64ビットデータモデル
ILP32
(Win*32, UNIX*32, Linux*32)
LP64
(UNIX*64, Linux*64)
LLP64
(Win*64)
ILP64
char8888
short16161616
int32323264
long32643264
long long64646464
size_t32646464
ポインタ32646464

1. ワーニングの抑制

どんなソフトウェアの書籍においても、ワーニングレベルをできるだけ高く設定されていることが推奨されている。プロジェクトをこなしてきたプログラマは経験的に、そのソフトウェアに必要な品質を判断することができる。

しかし、64ビット化においては、重大なバグを見逃すことになる可能性があるので、その考えは改め全てのプロジェクトのワーニングレベルを最高に引き上げるべき。そうしないなら、以下のようなミスを見逃すことになる。

unsigned char *array[50];
unsigned char size = sizeof(array);

// 32bit環境:sizeof(array) = 200
// unsigned charの最大値は255なので400を代入すると変数がオーバーフローする。
// 64bit環境:sizeof(array) = 400

2. 可変個の引数をとる関数

64ビット環境でNGな例
const char *invalidFormat = "%u";
size_t value = SIZE_MAX;

// 64ビット環境ではsize_tは8Byteの符号なし整数型なのでこのコードはNG
printf(invalidFormat, value);


このようなバグは64ビット化だけではない。C++言語の本質的な危険性からきている。この問題を
避けるための方法として、そのような関数の使用は避け、より安全な関数を使うことである。例えば、printfの代わりにcout、sprintfの代わりにboost::formatやstd::stringstreamである。

もし、printfやscanf系の関数を利用したい場合は、以下のマクロを使うとよい。
size_t u;

scanf("%u", &u);  // Win32
scanf("%Iu", &u); // Win64
scanf("%lu", &u); // Linux64

3. マジックナンバー

質の低いコードはマジックナンバーを含んでいる。マジックナンバーはその存在自体が危険であり、アドレス演算、オブジェクトのサイズ、ビット演算等に使われていた場合、64ビット化移植時が困難になる。

以下は64ビット化移植に影響する基本的なマジックナンバーである。


説明
4ポインタのバイト数
32ポインタのビット数
0x7fffffff32ビット符号付き整数の最大値、また32ビット型の最上ビットのマスク値として使われる
0x8000000032ビット符号付き整数の最小値、また32ビット型の最上ビットのマスク値として使われる
0xffffffff32ビット変数の最大値、またはエラー値-1として使われる

マジックナンバーは、sizeof()演算子やのマクロで置き換えるべきである。

64ビット環境でNGな例

// 1) intptr_tの動的領域確保にマジックナンバーを使用している。
//    intptr_tは32ビット環境では4byteだが64ビット環境ではは8byte
size_t ArraySize = N * 4;
intptr_t *Array = (intptr_t *)malloc(ArraySize);

// 2) 64ビット環境ではsize_tは8byte
size_t values[ArraySize];
memset(values, ArraySize * 4, 0);

64ビット環境でOKな例
// 1)
size_t ArraySize = N * sizeof(intptr_t);
intptr_t *Array = (intptr_t *)malloc(ArraySize);

// 2)
size_t values[ArraySize];
memset(values, ArraySize * sizeof(size_t), 0);

4. int型数値のdouble型変数への格納

32ビット環境では、intが4byteでdoubleが8Byteのためint値をdouble型変数に格納しても問題なかった。64ビット環境では、以下の図のとおりsize_t等の変数が8byteになるため変数がオーバーフローする可能性がある。
// 1) 32ビット これはOK
size_t val1 = SIZE_MAX; // size_tはunsigned intと同じで4バイト
double val2 = UINT_MAX;

// 2) 64ビット これはNG
size_t val1 = SIZE_MAX; // size_tは4バイトとなる
double val2 = UINT_MAX; // オーバーフロー

5. ビットシフト

64ビット環境のことをあまり考えずにビットシフトをすると、以下のような問題に陥ることがある。

64ビット環境でNGな例
ptrdiff_t SetBitN(ptrdiff_t value, unsigned int bitNum)
{
// 1はint型リテラルなので、4Byteの範囲しか値を取ることができないため、
// 8Byte変数のビットシフトができない可能性がある
ptrdiff_t mask = 1 << bitNum;

return value | mask;
}

ここで何が起きているかというと、
以下の図のように32Bit変数に1の値が入っている場合、32回ビットシフトすると桁があふれて値が0となってしまう。一方、64Bit変数は32回以上ビットシフトしても値があふれることはない。



64ビット環境でOKな例
// 数値1のptrdiff_t変数を生成する
ptrdiff_t mask = ptrdiff_t(1) << bitNum;

ptrdiff_t mask = CONST3264(1) << bitNum;

6. ポインタアドレスの保存

32ビット環境では、intとポインタのサイズがともに4Byteであるため、ポインタをintにキャストしてアドレス演算をすることができた。64ビット環境では、メモリサイズ型のuintptr_t型を使うと別アーキテクチャへ移植できて良い。

64ビット環境でNGな例

1) char *p;
p = (char *)((int)p & PAGEOFFSET); // ポインタをintにキャストしてはいけない

// mallocの戻り値(void *)をDWORD(unsigned int)にキャストしてはいけない
2) DWORD tmp = (DWORD)malloc(ArraySize);

64ビット環境でOKな例

1) char *p;
p = (char *)((intptr_t)p & PAGEOFFSET);

2) DWORD_PTR tmp = (DWORD_PTR)malloc(ArraySize);

64ビット環境でも少ないメモリしか利用していない時は再現しないので、非常に発見が困難なバグになり得る。上記NG例はメモリ使用量が4GBを超えた時点で、動作は未定義となる。

8. 配列のキャスト

64ビット環境では、配列のキャストが危険な場合とそうでない場合がある。
int array[] = {1, 2, 3, 4};
enum ENumbers {ZERO, ONE, TWO, THREE, FOUR};

// 安全なキャスト
ENumbers *enumPtr = (ENumbers *)(array);
cout << enumPtr[1] << " ";

// 危険なキャスト
size_t *sizePtr = (size_t *)(array);
cout << sizePtr[1] << endl;

// 32ビットプログラムでの出力結果: 2 2
// 64ビットプログラムでの出力結果: 2 17179869187


ここで何が起こっているというと、以下の図のように64ビット環境でint、enum型は4Byteだがsize_t型は8Byteのためである。

9. メモリサイズ型を引数に持つvirtualなメンバ関数

virtualなメンバ関数をもつ多くなクラスがある場合、不注意でメモリサイズ型を別の型と混同して使ってしまうことがある。32ビット環境はこれでも問題ない。例えば、基底クラスのvirtualなメンバ関数にsize_tを使い、派生クラスにはunsignedを使ったとしよう。64ビット環境では問題が生じてしまう。

しかし
class CWinApp {
...
virtual void WinHelp(DWORD_PTR dwData, UINT nCmd);
};
class CSampleApp : public CWinApp {
...
virtual void WinHelp(DWORD dwData, UINT nCmd);
};

ここでアプリケーション開発のライフサイクルを考えてみよう。例えば、Microsoft Visual C++ 6.0を使ったCWinAppクラスのWinHelp関数を以下のようにプロトタイプ宣言したとする。
virtual void WinHelp(DWORD dwData, UINT nCmd = HELP_CONTEXT);

派生クラスのCSampleAppでこの関数をオーバーライドすることに特に問題はない。その後、このプロジェクトはMicrosoft Visual C++ 2005にポーティングしたとする。

FC2→Bloggerに移行する際にやったこと


※以下の設定メモは2012/12/09時点です。Bloggerがバージョンアップすれば手順が変わる可能性があります。

  • FC2からブログ記事をBloggerにインポートする
以下のサイトの手順で問題なく移行可能
http://ss117935.blogspot.jp/2012/05/fc2-blogger.html
  • デザインテンプレートを設定する
Blogger Templatesのページから好きなテンプレートをダウンロードし、以下の手順でBloggerに設定する。
  1. ダウンロードしたページを解凍し、“テンプレート名.xml” ができる
  2. Bloggerの管理ダッシュボード→「テンプレート」→「バックアップ/復元」をクリック
  3. 「ファイルを選択」をクリックし、Bloggerに、“テンプレート名.xml”をアップロードする

  • Google Code Prettifyを導入してコードのシンタックスハイライトをする
Bloggerの管理ダッシュボード→「テンプレート」→「HTMLの編集」を開き、以下のコードをheadタグ内のどこかに挿入する。すると、GoogleのCDNからjquery, prettifyを取得して<pre class=”prettyprint”></pre>内のコードをシンタックスハイライトしてくれる。
<!-- jquery 1.7.2 -->
<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js' type='text/javascript'/>

<!-- Google Prettify -->
<link href='http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css' rel='stylesheet' type='text/css'/>
<script src='http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js' type='text/javascript'/>
<script type='text/javascript'>
$(function() {
  prettyPrint();
});
</script>
</head>

  • table要素のスタイルを設定する
Bloggerの管理ダッシュボード→「テンプレート」→「カスタマイズ」→「アドバンス」→「CSSを追加」をクリックし、以下のコードを追加する

table {
    border: 1px #E3E3E3 solid;
    border-collapse: collapse;
    border-spacing: 0;
}

table th {
    padding: 5px;
    border: #E3E3E3 solid;
    border-width: 0 0 1px 1px;
    background: #F5F5F5;
    font-weight: bold;
    line-height: 120%;
    text-align: center;
}
table td {
    padding: 5px;
    border: 1px #E3E3E3 solid;
    border-width: 0 0 1px 1px;
    text-align: center;
}

参考にさせて頂いたページ

クリボウのBlogger Tips
http://www.kuribo.info/

2012年12月8日土曜日

Photosynth - from my beloved room in Osaka

Photosynthでバルコニーからのパノラマ写真を作ってみた☆



Open Street Map - Haiti

Maybe you have never heard about it so I am gonna explain a little bit about what Open Street Map (OSM) is first. Open Street Map is maps for open source where anybody can join and create a portion of maps and use it for free.You might wonder if it is the same as Google Maps but it's different. Google maps is actually NOT open source, you can use it for free as well though. The whole contents of Google maps are licensed by Google and you have to pay certain amount of money if you want to use it for the purpose that Google may want that to happen without being paid (i.e. for commercial use).

So real open source map is only Open Street Map not Google maps, Yahoo, Bing maps and any other online maps. First I got to knew OSM is time when I participated in Open Source Conference Tokyo 2010 on August 11th. I joined a session about OSM and the guys out there got me interested by the following awesome video.

OpenStreetMap - Project Haiti from ItoWorld on Vimeo.


The video illustrates how the maps for Haiti was created over time right after the earth quake occurred. From what I've heard, one of the community members of OSM came up with that idea in oder to help Haitian people. The best part is not only lots of people in the community participated (what we call Mapper) but ito made awesome video to encourage more people get interested in the activities. Here is another video.

Open Street Map 2008 Map Edits from Peter Dunn on Vimeo.


I got soooo interested in OSM and came to think what I can do something for them. I've heard it's so easy to become a mapper so I am gonna register the OSM user and draw some maps around my place for starters.

Hourai Bridge





C#でPOSTメソッドを使用する

@ITの記事のC#でPOSTメソッドほぼ写経。

WebRequest/WebResponseクラスでPOSTメソッドによりデータを送信するには?
http://http://www.atmarkit.co.jp/fdotnet/dotnettips/318webpost/webpost.html

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Net;

class Program
{
    static void Main(string[] args)
    {
        // POSTする対象のURL
        string url = "http://www.rarejob.com/login/top.php?mode=off&";
        // POSTメソッドで渡すパラメータ
        string param = "";

        // Dictionaryオブジェクト
        var dic = new Dictionary<string, string>();
        dic["USER_ID"] = "メールアドレスを指定";
        dic["PASSWORD"] = "パスワードを指定";

        // POSTメソッドのパラメータ作成
        foreach (string key in dic.Keys)
            param += String.Format("{0}={1}&", key, dic[key]);

        // paramをASCII文字列にエンコードする
        byte[] data = Encoding.ASCII.GetBytes(param);

        // リクエスト作成
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
        request.Method = "POST";
        request.ContentType = "application/x-www-form-urlencoded";
        request.ContentLength = data.Length;

        // ポストデータをリクエストに書き込む
        using (Stream reqStream = request.GetRequestStream())
        reqStream.Write(data, 0, data.Length);

        // レスポンスの取得
        WebResponse response = request.GetResponse();

        // 結果の読み込み
        string htmlString = "";
        using (Stream resStream = response.GetResponseStream())
            using(var reader = new StreamReader(resStream, Encoding.GetEncoding("Shift_JIS")))
            htmlString = reader.ReadToEnd();

        // 結果の出力
        Console.WriteLine(htmlString);

        Console.Write("Press enter to end:");
        Console.ReadLine();
    }
}