RAD Studio 2007用とRAD Studio 2009用のIDE Fix Pack 2.1が公開されました。
RAD Studio 2007用とRAD Studio 2009用のIDE Fix Pack 2.1が公開されました。
開発者のAndreas Hausladenさんのブログ
« 2008年11月 | メイン | 2009年01月 »
RAD Studio 2007用とRAD Studio 2009用のIDE Fix Pack 2.1が公開されました。
開発者のAndreas Hausladenさんのブログ
2008年12月3日、盛況のうちに終了した第11回エンバカデロ・デベロッパーキャンプのプレゼンテーション資料をダウンロードいただけます。
第11回 エンバカデロ・デベロッパーキャンプの資料がダウンロードできるようになりました。
参加者の方々のブログを読んでいると面白そうで、参加できなかったことが残念です。
この資料を読んで、勉強します。
第11回 エンバカデロ・デベロッパーキャンプの資料にある「Delphiでのマルチスレッドプログラミング」を読んで。
TThreadの排他制御にSynchronizeの他にQueueという機能がDelphi2005から追加されたそうです。
これは知りませんでしたので、早速試してみました。
まずはSynchronizeから。
//---------------------------------------------------------------------------
void __fastcall TSampleThread::Execute()
{
FMsg = "Start";
Synchronize(&WriteMsg);
FMsg = "End";
Synchronize(&WriteMsg);
}
//---------------------------------------------------------------------------
void __fastcall TSampleThread::WriteMsg()
{
Sleep(1000);
Form1->Memo1->Lines->Add(FMsg);
}
Synchronizeは並行動作ではないため、実行が終わるまでワーカースレッドは待たされます。
実行結果は次のようになります。
Start
End
次に新機能のQueueです。
//---------------------------------------------------------------------------
void __fastcall TSampleThread::Execute()
{
FMsg = "Start";
Queue(&WriteMsg);
FMsg = "End";
Queue(&WriteMsg);
}
//---------------------------------------------------------------------------
void __fastcall TSampleThread::WriteMsg()
{
Sleep(1000);
Form1->Memo1->Lines->Add(FMsg);
}
Queueでは、メインスレッド側の実行は非同期で並行して行われます。
実行結果は次のようになります。
End
End
WriteMsg()の中でSleep(1000)している間に、Execute()でFMsgが"End"に更新されています。
SynchronizeとQueueを上手に使い分けることで、より効率の良いプログラムができそうです。
第11回 エンバカデロ・デベロッパーキャンプの資料にある「単層から多層アーキテクチャへの遷移」を読んで。
Delphi2009に搭載されたDataSnap 2009は、すごく簡単で便利そう。
非常に強力なコンポーネントのようです。
使ってみたいとは思いますが、DataSnap2009が搭載されているのはEnterprise版かArchitect版で、Professional版では搭載されていませんよね。残念。
C++Builder版では制限があるようです。
C++BuilderにおけるDataSnap 2009のサポートについて
第11回 エンバカデロ・デベロッパーキャンプの資料にある「開発効率を飛躍的に高めるコンポーネント自作テク ニック」 を読んで。
すばらしい資料ですね。
自作コンポーネントの作成方法がよくまとまっています。
あまり見かけない情報ですから、大変貴重な資料だと思います。
第11回 エンバカデロ・デベロッパーキャンプの資料にある 「Delphi/C++Builder オープンソースコンポーネント実践活用法」 を読んで。
これもすばらしい。
大変有益な情報です。
ありがとうございます。
紹介されているDelphi/C++Builder用フリーコンポーネント。
時間があったら試してみたいと思います。
JVCLのコンポーネント紹介も助かります。
面白そうなコンポーネントがたくさんありますね。
JCL・JVCLはコンポーネントがたくさんありすぎて、使用を諦めていました。
もう一度挑戦したいと思いました。
JCLのインストール方法で、C++Builderでコンパイルエラーが発生した場合の対処方法についての記載があるのが嬉しいです。
第11回 エンバカデロ・デベロッパーキャンプの資料にある 「Delphi 2009ではじめるUnicodeアプリケーション - 既存コード移行のポイント」 を読みました。
Delphi 1からDelphi 2007までのバージョンから、Delphi 2009へコードを移行するためのポイントがまとめられています。
各バージョンでの移行作業がわかるすばらしい資料です。
移行しなければならないプログラムがたくさんありますので、大変助かります。
この資料を参考にして、移行作業を行います。
Delphi/C++Builder 2009のUnicodeに関する情報も充実してきました。
そろそろ本格的に2009に乗り換える時期ですね。
C++Builder2007まではコンパイルできた次のコードが、C++Builder2009ではコンパイルエラーになります。
String dir = "C:\\日本語.txt";
FILE* f = fopen(dir.c_str(), "rt");
[BCC32 エラー] File1.cpp(14): E2034 'wchar_t *' 型は 'const char *' 型に変換できない
[BCC32 エラー] File1.cpp(14): E2342 パラメータ '__path' は const char * 型として定義されているので wchar_t * は渡せない
StringがAnsiStringからUnicodeStringに変わったため、String#c_str()の返す型がchar*からwchar_t*に変わりました。
fopenには引数にchar*を受け取るfopen(char*)はありますが、wchar_t*を受け取るfopen(wchar_t*)は存在せず、C++Builder2009ではコンパイルエラーになります。
C++Builder2009でも一度AnsiStringに変換するか、_wfopenを使えば、コンパイル可能です。
# AnsiStringに変換
FILE* f = fopen(AnsiString(dir).c_str(), "rt");
# _wfopenを使用
FILE* f = _wfopen(dir.c_str(), L"rt");
AnsiStringに変換した方のコードはfopen(char*)を使用しますが、
FILE* fp = fopen("日本語.txt","rt");
あるいは
std::ifstream file("日本語.txt");
これ、現在のC/C++では正しく 日本語.txt が
オープンできる保証はどこにもないんです。少なくとも言語仕様としては。
なのだそうです。
コメント欄も勉強になります。
今まで意識したことがありませんでしたが、微妙な問題があるのですね。
C++0xでは、UTF-8, UTF-16, UTF-32の三つのUnicode符号化方式がサポートされる。
C++0xによって、このあたりがどのように変わるのでしょう。
Delphi 2009 と C++Builder 2009 の Update 2 がリリースされました。
このアップデートに含まれるのは、データベース関連の修正だけです。
今回のアップデートはデータベース関連の修正だけとのこと。
こまめに素早く修正がリリースされるのは嬉しいです。
多くの国の言語に対応する必要があったりと、リリース作業は大変だと思いますが、頑張って下さい。
Delphi 2009 および C++Builder 2009 Help Update 1 には、ヘルプ システムのバグ修正のほか、改良がいくつか施されています。
ということで、Delphi / C++Builder 2009 のHelp Update 1がリリースされました。
PyScripterはPython用の統合開発環境です。
Eclipseよりもずっと軽いのが魅力です。
PyScripter1.9.9.3がリリースされました。
pyscripter - PyScripter Development Site
gettextが組み込まれたため、このバージョンより言語の選択ができるようになりました。
日本語化パッチも必要ありません。いい感じですね。
とのことで、pyscripterのサイトを見てきました。
Debugging django applications with PyScripter
Djangoアプリケーションをデバッグするために必要な設定方法が記されています。
どうやら、簡単な設定でDjangoアプリケーションのデバッグができそうです。
Using PyScripter with Portable Python
Portable PythonやMovable Pythonを使えば、簡単にPyScripterが使えるよ。
ということ?
Shortcut and highlighter schemes
IDEのショートカットやハイライトの設定を変更できる?
各種設定が用意されています。
Python 3.0 support
Python 3.0のサポート。
自作のプログラムを少しずつ移行しなくちゃ、といつも思う。
Localization
うれしい日本語対応です。
C++のクラス定義を復習する。
クラス定義の基本形。
class Foo
{
};
内部クラス。クラス定義の中に他のクラスを定義できる。
Javaと違い、外部クラスとの関連はない。
class Outer
{
public:
class Inner
{
public:
void say()
{
std::puts("Hello");
}
}:
};
Outer::Inner c;
c.say();
内部クラスによく似たもので、無名クラス。
C言語の無名構造体のC++版。
class Outer
{
public:
class
{
public:
void say()
{
std::puts("Hello");
};
} inner;
};
Outer c;
c.inner.say();
クラスは関数内でも定義できる。
int main(int argc, char* argv[])
{
class Outer
{
};
Outer o;
return 0;
}
おなじみテンプレートクラス。
template<class T>
class Foo
{
public:
T data;
};
Foo<int> foo;
foo.data = 1; //dataはint型。
テンプレートには、型パラメータの他に、非型パラメータも定義できる。
非型パラメータはint、short、charなどの整数値か列挙型が使える。
template<class T, int size>
class Foo
{
T data[size];
};
Foo<int, 10> foo;
内部クラスにもテンプレートを使用できる。
class Outer
{
public:
template<class T>
class Inner
{
public:
T data;
};
};
Outer::Inner<int> c;
c.data = 1; //dataはint型
外部クラスのテンプレートは、内部クラスにも有効。
template<class T>
class Outer
{
public:
class Inner
{
public:
T data;
};
};
Outer<int>::Inner c;
c.data = 1; //dataはint型
これを使うと、コンパイル時に内部クラスを一括して設定することができる。
template<class T>
class Outer
{
public:
class Inner1
{
T data;
};
class Inner2
{
T data;
};
class Inner3
{
T data;
};
};
パラメータ化継承。上位クラスをパラメータにすることができる。
template<class SuperClass>
class Foo : public SuperClass
{
};
パラメータ化継承を使うと、柔軟かつ強力なクラス設計ができる。
template<class SuperClass>
class Employee : public SuperClass
{
};
template<class SuperClass>
class Customer : public SuperClass
{
};
template<class SuperClass>
class Shareholder : public SuperClass
{
};
class Person
{
};
Employee<Person> a;
Shareholder<Employee<Person> > b;
Shareholder<Employee<Customer<Person> > > c;
クラスの設計情報をパラメータ化することもできる。
struct ConfigA
{
typedef int Price;
};
struct ConfigB
{
typedef double Price;
};
template<class Config>
class Product : public Config
{
public:
typedef typename Config::Price Price;
Price price;
};
Product<ConfigA> a;
a.price = 1; //priceはint型
Product<ConfigB> b;
b.price = 2.3; //priceはdouble型
C++のテンプレートはパラメータとして関数をとることができる。
/**
* 3倍する
*/
int treble(int x)
{
return x * 3;
}
/**
* 4倍する
*/
int quadruplicate(int x)
{
return x * 4;
}
/**
* 引数を計算式で計算する
* @param function int型の引数をとりint型を返す関数
* @param a 計算する値
* @return 計算結果
*/
template<int function(int)>
int calc(int a)
{
return function(a);
}
//2を3倍する
int num1 = calc<treble>(2);
//3を4倍する
int num2 = calc<quadruplicate>(3);
まずパラメータ継承を使わないテンプレートメソッド。
Wikipediaの例を参考にした。
StringListerで定義されている抽象メソッドformatItem()が、display()内で使われている。
class StringLister
{
public:
virtual std::string formatItem(std::string item) = 0;
void display(std::string item)
{
std::cout << formatItem(item) << std::endl;
}
};
class PlainTextStringLister : public StringLister
{
public:
virtual std::string formatItem(std::string item)
{
return "- " + item;
}
};
class HtmlStringLister : public StringLister
{
public:
virtual std::string formatItem(std::string item)
{
return "<li>" + item + "</li>";
}
};
PlainTextStringLister().display("Foo"); //=> - Foo
HtmlStringLister().display("Foo"); //=> <li>Foo</li>
パラメータ継承を使ったテンプレートメソッド。
ConcreteClassのメソッドformatItem()が、display()内で使われている。
template<class ConcreteClass>
class StringLister : public ConcreteClass
{
public:
void display(std::string item)
{
std::cout << ConcreteClass::formatItem(item) << std::endl;
}
};
class PlainTextStringLister
{
protected:
static std::string formatItem(std::string item)
{
return "- " + item;
}
};
class HtmlStringLister
{
protected:
static std::string formatItem(std::string item)
{
return "<li>" + item + "</li>";
}
};
StringLister<PlainTextStringLister>().display("Foo"); //=> - Foo
StringLister<HtmlStringLister>().display("Foo"); //=> <li>Foo</li>
C++Builder2009では文字列がUnicode文字列に変更された。
この変更に伴い、Win32APIの呼び出しも変更された。
ヘルプには次のように記載されている。
API はデフォルトで WideString("W")版を呼び出します。
ms-help://embarcadero.rs2009/devcommon/unicodeinide_xml.html
ところが実際は、「プロジェクトオプション」の「ディレクトリと条件定義」で「_TCHARのマップ先」を「char」から「wchar_t」に変更する必要がある。
ヘルプの「_TCHAR のマップ先」の項目には次のように記載されている。
[wchar_t] を選択すると、以下のように動作します。
- UNICODE と _UNICODE が定義されます。
- リンカはワイド バージョンのライブラリを使用します。
- 標準ライブラリと Windows API の関数は、ワイド定義に設定されます。
ms-help://embarcadero.rs2009/devcommon/dirconditionals_xml.html
「_TCHARのマップ先」の初期値は「char」であるため、WideString版のAPIは呼び出されない。
初期値が「wchar_t」なら、ヘルプの記載も正しいのだが。
AnsiStringTのコンストラクタにchar*とwchar_t*を引数とした場合の挙動のテスト
const char* c1 = "テスト";
AnsiStringT<20932> euc1(c1);
ShowCode(euc1);
const wchar_t* c2 = L"テスト";
AnsiStringT<20932> euc2(c2);
ShowCode(euc2);
実行結果
CodePage = 20932
83 65 83 58 83 67
CodePage = 20932
a5 c6 a5 b9 a5 c8
char*の場合は変換されず、コードページと文字が一致していない。
コードページはEUC-JPだが、Shift_JISのバイト列のままである。
wchar_t*を引数とした場合は、EUC_JPに変換されている。
代入の場合も同じ動作となる。
今回の検証に使用した関数
void ShowCode(const RawByteString& Str)
{
printf("CodePage = %d\n", StringCodePage(Str));
for (int i = 1; i <= Str.Length(); i++)
{
printf("%x ", static_cast<unsigned char>(Str[i]));
}
printf("\n");
}
AnsiStringTからコードページの異なるAnsiStringTへの代入のテスト
AnsiStringT<932> sjis = L"テスト";
AnsiStringT<20932> euc = sjis;
ShowCode(euc);
実行結果
CodePage = 20932
a5 c6 a5 b9 a5 c8
コードページにしたがって変換されている。
UnicodeStringを間に挟んだ場合のテスト
AnsiStringT<932> sjis = L"テスト";
UnicodeString uni = sjis;
AnsiStringT<20932> euc = uni;
ShowCode(euc);
実行結果
CodePage = 20932
a5 c6 a5 b9 a5 c8
Shift_JISからEUC-JPに変換されている。
結論としては、
AnsiStringTからAnsiStringTへの代入、
AnsiStringTからUnicodeStringへの代入、
UnicodeStringからAnsiStringTへの代入、
は、いずれも自動的に変換されるようだ。
今回の検証に使用した関数
void ShowCode(const RawByteString& Str)
{
printf("CodePage = %d\n", StringCodePage(Str));
for (int i = 1; i <= Str.Length(); i++)
{
printf("%x ", static_cast<unsigned char>(Str[i]));
}
printf("\n");
}
RawByteStringの動作のテスト
RawByteStringのコンストラクタのテスト
char*を受け取るコンストラクタ
RawByteString raw("テスト");
ShowCode(raw);
実行結果
CodePage = 65535
83 65 83 58 83 67
バイト列をそのまま変換しないで保持している。
wchar_t*を受け取るコンストラクタ
RawByteString raw(L"テスト");
ShowCode(raw);
実行結果
CodePage = 932
値が空になっている。
RawByteString(wchar_t*)は引数が無効になるので注意が必要だ。
代入のテスト
const wchar_t* c = L"テスト";
AnsiStringT<20932> euc(c);
RawByteString raw = euc;
ShowCode(raw);
実行結果
CodePage = 20932
a5 c6 a5 b9 a5 c8
コードページも文字のバイト列も変換しないで、そのまま保持している。
UnicodeString uni = "テスト";
RawByteString raw = uni;
ShowCode(raw);
実行結果
CodePage = 932
UnicodeStringをRawByteStringに代入すると空になる。
wchar_t*を引数にとるコンストラクタと同じ挙動だ。
今回の検証に使用した関数
void ShowCode(const RawByteString& Str)
{
printf("CodePage = %d\n", StringCodePage(Str));
for (int i = 1; i <= Str.Length(); i++)
{
printf("%x ", static_cast<unsigned char>(Str[i]));
}
printf("\n");
}