トップ 差分 一覧 ソース 検索 ヘルプ PDF RSS ログイン

独り言日記(2008/10)

独り言日記

Macでのヘルプの実装方法(2008/10/23)

アプリケーションでのMacでのヘルプの実装方法の覚え書きです。MacではHelpBookというそうです。

http://developer.apple.com/documentation/Carbon/Conceptual/ProvidingUserAssitAppleHelp/user_help_intro/chapter_1_section_1.html

結構試行錯誤した点があるのでそれを強調して書きます。

ヘルプの元をHTMLにて作成

[test]
     test.html
     test2.html

みたいなファイル構成を行い、開始ページはindex.htmlじゃなくてフォルダ名と同一のもの(ここでは「test」)としています。もちろん、CSSや画像ファイルなどはそのままHTMLとして作成、配置していきます。フォルダは階層構造になっていてOKです。a hrefでリンクをたどることができるようにしておきます。

トップページ(ここではtest.html)にてアプリケーションで識別する名称を入れる

test.htmlをテキストエディタで開き、ヘッダ部分を見ます。

<html>
<head>
<title>トップページのタイトル</title>
<meta http-equiv=Content-Type content="text/html;  charset=SHIFT_JIS">
<META NAME="AppleTitle" CONTENT="MyApp">
<link rel="stylesheet" type="text/css" href="./style.css" />
</head>

まず、日本語の検索をまともに行えるようにするにはShiftJISである必要があるようです。これは1つめのメタタグで指定してる部分。もちろん、ファイルはShiftJIS(Macの場合はファイルエンコーディングを「日本語(MacOS)」)にして保存します。

2つめのメタタグにて、「AppleTitle」というのに「MyApp」としています。これは、アプリケーションサイドから呼ぶ場合に必要な識別名です。

最低限、この2つがトップページに設定されていれば認識できます。その他、キーワード指定やアイコン指定などがあります。上に書いているURLのAppleのサイトに詳しく書いてます。

インデックスの作成

XCodeをインストールしたときにDeveloperというフォルダが作成されています。ここの「/Developer/Applications/Utilities/Help Indexer」を起動します。これがヘルプのインデックス(索引)ファイルを作るアプリケーションとなってます。

Help IndexerのメニューよりPreferenceを選択し、設定ダイアログを出します。Minimum term lengthを1tokenに変更し、OKボタンを押します。

フォルダ指定のダイアログにて、先ほど作成した「test」フォルダを指定します。「CreateIndex」ボタンを押すと処理が開始され、「test.helpindex」というファイルが「test」フォルダ内に生成されます。

[test]
     test.html
     test.helpindex  <= New!!
     test2.html

な感じ。

アプリケーション側のInfo.plist

XCodeにて、Info.plistをプロジェクトに加えていると思いますが、これを開きます。以下2行がない場合は追加します。

<key>CFBundleHelpBookFolder</key>
<string>test</string>
<key>CFBundleHelpBookName</key>
<string>MyApp</string>

「CFBundleHelpBookFolder」のstringにて、作成したインデックスおよびフォルダ名であるtestを指定、「CFBundleHelpBookName」のstringにて、test.htmlのメタタグAppleTitleで指定した名称を指定します。

日本語リソースのフォルダを作成し、プロジェクトに追加

「Japanese.lproj」というフォルダを作成します。その中に「InfoPlist.strings」というテキストファイルを作成していれる、先ほどの[test]フォルダを丸々コピーします。

[Japanese.lproj]
     InfoPlist.strings
     [test]
          test.html
          test.helpindex
          test2.html

この「Japanese.lproj」をXCodeの「Resources」グループに入れるわけですが、ポップアップメニューの追加-既存のファイルにて追加する際に、参照タイプは「内包しているグループを基準」、ラジオボタンの「追加したフォルダにフォルダ参照を作成する」を選択するようにします。これを間違えるとアプリケーションパッケージにフォルダ階層がない状態で展開されてしまいますので、ヘルプを呼び出すことができなくなります。

ついでに。Japaneseとあるのでわかると思いますが、Englishやその他のローカライズも「XXXX.lproj」フォルダに分けていれることで、リソースを言語別に(ヘルプも含めて!)分離できるのがわかりますね。

後、「InfoPlist.strings」の中身をテキストファイルとして編集します。

CFBundleName = "アプリケーション名";
NSHumanReadableCopyright = "Copyright © 2008-2008 自分の会社名など";

アプリケーション名は、アプリ起動時にAppleメニューの右に表示される名称です。コピーライトはそのまんま、コピーライト情報を記載します。なお、UTF-8で保存するようにしてください。

以上にて、リソース関連の設定はOKです。まだ、Carbonのプログラムの場合は細工がいります。

プログラムの先頭にて以下を追加

プログラムの開始部分(初期化部分)にて、

 CFBundleRef myApplicationBundle;
 CFURLRef myBundleURL;
 FSRef myBundleRef;
 OSStatus err = noErr; 
 myApplicationBundle = NULL;
 myBundleURL = NULL;

 myApplicationBundle = CFBundleGetMainBundle();
 if (myApplicationBundle == NULL) { err = fnfErr; }
 if(err == noErr) {
   myBundleURL = CFBundleCopyBundleURL(myApplicationBundle);
   if(myBundleURL == NULL) { err = fnfErr; }
   if(err == noErr) {
     if(!CFURLGetFSRef(myBundleURL, &myBundleRef)) err = fnfErr;
     if (err == noErr) err = AHRegisterHelpBook(&myBundleRef);
   }
}	

を挿入します。Appleのサイトの例そのままですが、HelpBookをキックできるように登録処理を行ってます。はじめの1回だけでOKです。

後は、XCodeにてアプリケーションをビルドします。パッケージ内のResourcesフォルダに「Japanese.lproj」以下がそのまま入っていればOKです。

これで、アプリ起動にてメニュー一番右端の「ヘルプ」より検索、トップページ呼び出しのファイルメニューが表示されてます。

というところまでたどり着くまでに結構苦労してしまいました。Macのヘルプはインデックスの一覧表示はないんですね。ですが、単なるHTMLヘルプではありますので、Windowsと大部分は共通化できそうではあります。

続・Macでのメモリ管理が怪しい?(2008/10/22)

うむ、この問題、Shadeでもまったく同じですな。実メモリ700MBくらい消費で待たされてます。ということで、Apple突付きはイーフロにバグレポートするとして間接的につついてもらおう。英語できる方いらっしゃるでしょうし。この際、巻き込んでしまえ(苦笑)。

Macでのメモリ管理が怪しい?(2008/10/22)

Macにてパフォーマンスチューニングしていて、気になるというか「回避できないかも」というでかい問題に出くわしました。

大きなhdrファイル(約50MB)をメモリ上に展開している部分です。メモリでは6000x3000pixelでRGBE4バイト/pixelにて、約72MBになります。これを単純にメモリ確保しているところをアクティビティモニタで観察してみました。

hdrファイル読み込み+メモリへの展開は数秒で終わるのですが、その後大量にメモリを消費。650MBくらい何やってるんだろう、という不振な動きをしてます。この間、当然ながらアプリケーションは動作がカクカクになってしまいます。1分くらい待つと、メモリ使用量はがたっと減って元のメモリ使用量に戻ります。

メインスレッドでのメモリ確保・サブスレッドでのメモリ確保、両方試したのですが同じ。再現率100%ですが、アプリ開始時の初期化処理での読み込みでは問題なかったり。同じルーチンを通ってるのになぁ。

メモリ確保量が小さい場合は問題ないです。Winではまったく問題ない部分なので、どうもOSのバグっぽいなぁ。試しにファイル読み込みはせずに単純に

int wid, hei;
wid = 6000;
hei = 3000;
char *pBuff = (char *)malloc(wid * hei * 4);
free(pBuff);

みたいなコードを流しこんでみてもやっぱり同じ状態に。

う〜む、もうちょっとこじんまりしたソースで再現性を確認してAppleに申告したほうがよいのだろうか・・・。自分アプリの何かがトリガーになってる可能性ももちろんありますけど、3D関連のツール類にてメモリ確保処理でこれくらいでへこたれてしまってはちと困りますねぇ。動き的にはメモリ解放を遅延させるガベージコレクションっぽい動きではあるのですが、、誰か同じ現象に出くわしてないかな。解決策が見つからん・・・。

追伸:

Mac標準アプリの「プレビュー」では6000x3000pixelのhdrを見るともっとえらいことになりますね。メモリ消費量は実メモリ700MBくらい、5分くらい待ってようやく出てきました。しかも、高解像度な画像のはずなのにボケボケじゃないすか。メモリ1GB積んでいるMacBookなんですが、、、。

wxWidgetsのMac版(wxMac)でのAUIのバグを修正(2008/10/21)

下に書いたMac版wxWidgetsのAUIにて、フローティングウィンドウが移動するたびに縦方向に小さくなる問題を修正してみました。wxMac 2.8.9にて。「src/aui/framemanager.cpp」を編集します。変更箇所はwxAuiManager::Update関数内です。

 if (p.IsFloating())
 {
     if (p.frame == NULL)
     {
             frame->SetPaneWindow(p);
             p.frame = frame;

             // 以下を追加する
#if __WXMAC__
             p.frame->SetSize(p.floating_pos.x, p.floating_pos.y,
                      p.floating_size.x, p.floating_size.y + 28,
                      wxSIZE_USE_EXISTING); 				
#endif

               if (p.IsShown() && !frame->IsShown())
                  frame->Show();
     }
     else
     {
            // 以下を追加する 
#if __WXMAC__
              if ((p.frame->GetPosition() != p.floating_pos) ||
                   (p.frame->GetSize().GetWidth() != p.floating_size.x ||
                   p.frame->GetSize().GetHeight() != p.floating_size.y + 16))
#else
              if ((p.frame->GetPosition() != p.floating_pos) || (p.frame->GetSize() != p.floating_size))
#endif

                {					
                   p.frame->SetSize(p.floating_pos.x, p.floating_pos.y,
                   // 以下を追加する
#if __WXMAC__
                                    p.floating_size.x, p.floating_size.y + 16,
#else
                                    p.floating_size.x, p.floating_size.y,
#endif
                                    wxSIZE_USE_EXISTING);
 
                 // 以降は同じ              
     }
 }

WXMAC」と表記した部分を追加しました(WXMACはMacのためのプリプロセッサです)。何を変更したのかというと、「wxAuiPaneInfo.GetSize().GetHeight()」で取得できる高さと「wxAuiPaneInfo.floating_size.y」での高さはキャプション分の差がある、という部分を吸収しています。その差はちょうど16pixelになってます。

どうも、AUI上ではフレームのサイズと保持しているフローティングウィンドウの高さを同じものとしているようですが、実際はキャプション分を上乗せしていないため、ずれてしまいます。この場合はUpdateが呼ばれる(=移動する)たびにどんどん縦方向に縮んでいくんですね。

「 if (p.frame == NULL)」のカッコ内は、一番始めにフローティングウィンドウを出すときに通ります。wxAuiManage::LoadPerspectiveの処理時、ドッキングからフローティングウィンドウに移行するときなど。なぜ28を加算しているかは、、、なんででしょう。いずれにせよ、これでずれなくなりました。

ということで、手を加えないはずのwxWidgets内に手を入れてしまいました。

wxWidgetsのMac版(wxMac)でのAUIでのフローティングウィンドウのずれ(2008/10/21)

wxWidgetsのMac版にてAUIも使えるのですが、サンプルのもそうですがフローティングウィンドウを移動させると高さが-16小さくなりますね。なので、移動するたびにどんどん小さくなります。ソース上はframemanager.cppのUpdate関数内を修正すればよいのかな。

サブスレッドからOpenGL命令を呼んではいけない(2008/10/20)

自分用メモ。

OpenGLの命令(glXXXXの関数)は、メインスレッドでないところから呼ぶとMac環境では落ちてしまいます。Windowsではいけるのですが、OS依存をなくすためにOpenGL処理はメインスレッドでキックできるような仕組みにするほうがよさげです。クリティカルセクションで保護してもアウトだったので、単純に「メインスレッドから呼ぶべし」という条件のようですね。

後、これは当たり前ではありますが複数スレッドからOpenGL命令をキックしないこと(上と同じ意味になりますね)。バッティングした場合にどう動くかはドライバの判断になりますので、可能なら直列で(Queue管理でもして)送るように。ただ、VistaとかOSレベルでハード(これはOpenGLというよりもDirectXですが)に密着してるものでは、さすがに対応しているのかもしれません。が、そのあたりはよく分かりません。

後、VistaはOpenGLの実装の仕方によってはほんとに簡単なアプリであっても激重になります。マルチコアでかつVistaでは不安定、なのは新しいドライバに変えたとしても起こりえる場合がありますので、このあたりは作法で回避、です。wxWidgetsのOpenGLのwxGLCanvasでは今のところ重くはなってないです。これ、ちょっと前までは自前OpenGLでやってたのですがかなり不安定でした。何がトリガーなんでしょうね。

Mac OS XのXCode3.0でのwxWidgets(2008/10/18)

XCode 3.0にて、wxWidgets(今は2.8.9)をビルドしてみたときの覚え書きです。

http://www.wxwidgets.org/

からMac版のソースをダウンロードしてビルドします。一筋縄ではいきません(^_^;;。gccのコマンドラインからでは簡単なんですけどね。

どれがプロジェクト?

wxMac-2.8.9/src内の「wxWindows.xcodeproj」をXcode3.0にて開きます。はじめに「src」内に作業領域を作るか、みたいなのを聞いてくるのでOKですすめます。これで、srcディレクトリ内に「build」ディレクトリができ、ここにコンパイル、ビルドしたファイルが入ります。

setup.hの設定

XCodeでの「グループとファイル」のツリー表示されてる部分より、wxWidgets/include/wx/setup.hを開きます。OpenGLを使用する場合は「wxUSE_GLCANVAS」を1に、トグルボタンを使う場合は「wxUSE_TOGGLEBTN」を1にします(Macの場合はなぜかデフォルト0になってる)。

UnicodeにてwxWidgetsを統一したほうが後々楽ですので「wxUSE_UNICODE」も1にします。

ソースをいじる

wxAuiToolBarというクラスを定義していないのになぜか使ってる箇所があるのでコメントアウト。/src/aui/framemanager.cppのAddPane関数内の「if (pinfo.HasGripper())」の部分をすべてコメント化。

ターゲットSDKの変更

「wxWindows」プロジェクトの「情報をみる」にて、「一般」の「ターゲットSDKを使用したクラス開発」で、「Mac OS X 10.4(Universal)」を選択。0S X 10.5のままだとwxWidgetsに限らず、うまいこといかない場合がありました。不安定なのかな。

コンパイラオプション変更

wxWindowsプロジェクトの「情報を見る」より、ビルドオプションの「インラインメソッドを隠す」をOnにする。staticの「情報を見る」より、ビルドオプションの「除去スタイル」を「すべてのシンボル」にする。「デッドコード除去」のOn、「デフォルトでシンボルを隠す」をOnにする。XCodeでは、コンパイラオプションがライブラリ側とアプリ側にて異なっている場合は警告が出るかエラーになるようです。鬼のように警告が流れる場合は、コンパイラオプションをライブラリ側とアプリ側で見比べてみるのがてっとりばやい解決策に結びつきそうです。

ビルド!!

「アクティブなビルド構成」をDeploymentにし、グループとファイルのターゲットにて「static」をビルドします。すると、build/Deployment/libwx_mac_static.aが生成されます。これがwxWidgetsの静的ライブラリです。

ということで、以上がXCodeでの静的ライブラリ「libwx_mac_static.a」を作成する手順です。

wxWidgetsを活用したいアプリケーション側では、ヘッダファイル、ビルドした静的ライブラリ、そしてフレームワークを参照する必要があります。以降は、ライブラリじゃなくてそれを利用するアプリサイドの設定です。

wxWidgetsヘッダファイルの置き場所

wxMac-2.8.9/src/build/include
wxMac-2.8.9/include

前者は「setup.h」の置き場所です。環境によって違いますので注意。これを、アプリケーションビルド時のヘッダ検索パスに入れます。

wxWidgetsライブラリの置き場所

wxMac-2.8.9/src/build/Deployment

先ほどビルドした静的ライブラリの出力先です。これをアプリケーションビルド時のライブラリ検索パスに入れます。

必要なライブラリ

「libwx_mac_static.a」をプロジェクトに加えます。

必要なフレームワーク

IOKit.framework
CoreFoundation.framework
System.framework
WebKit.framework
AppKit.framework
QuickTime.framework
Carbon.framework
GLUT.framework
AGL.framework
OpenGL.framework

GLUT/AGL/OpenGLはOpenGL関連にて必要です。

必要な動的ライブラリ

libz.dylib
libiconv.dylib

これらは/usr/libにあるやつです。wxWidgetsのプロジェクトからドラッグしてきました(XCodeのUI上での入力方法がわからん・・・)。

プリプロセッサの指定

__WXMAC__
__WXMAC_XCODE__

ビルドオプションの「プリプロセッサマクロ」という部分に上記を追加します。

後は、wxWidgetsのソースを書いてビルドするだけ。Windowsと同じアプリが出たときはなかなか感動です。画像リソースなどは再度設定しないといけないですね。

新しいMacBook(2008/10/15)

なんか発表になったようで。GeForceのグラフィック搭載はちょっとうらやましいです。

http://plusd.itmedia.co.jp/pcuser/articles/0810/15/news024.html

低価格のMacBookが値下げしてるし。最近MacBookを買ったばかりなのであちゃ〜、なんですが(^_^;;。ほしいときが買い時ではあったのでいたしかたないですね。

MacOSへレンダラを移植中ですが、Windowsでいう「WaitForMultipleObjects」の部分を構成から見直さないと速度アップできないなぁ。今のところ、1スレッド→2スレッドでのベンチにて1.5倍速程度。2倍にはしたいです。WindowsのCoreDuo機では純粋に2倍にいけてるのでいけるはず。しかし、レンダラはベンチマークというかCPUを極限まで使う処理に向いてますね。マルチコアばんざいです。

POSIXのセマフォにて交通整理してるのですが、複数からの了承待ち+タイムアウト時間がある待ち(WindowsのWaitForMultipleObjects)はsem_wait/sem_trywaitでは実装できません。というか、POSIXではその機能はないようでした。もう1つタイムアウト用のスレッド+複数待ちでの解除セマフォを用意すれば同等のことをできるような気がしますので、実験せねば。しかし、スレッドはスケジュール管理がパズルですね。コアレンダラ部は、速度面以外では移植は完了しました。なんとなくですが、「いや〜、昔に比べてMacは硬くなったなぁ(落ちにくいの意味で)」としみじみ思ってます。後、プログラムしやすいです。制御できる範囲はWindowsよりも上な気がしてます。開発側からしてみれば、Aquaの皮をかぶったUNIXだなぁ。スレッドというか割り込み部分はどことなくですが、PC-98を思い出しました(signalでの割り込み処理とか。[Ctrl]+[C]などもフックできますね)。

後、一部リトルエンディアンとビッグエンディアンの問題が発生する箇所があるのですが(bmp画像の扱いにて。できるだけ速く読み込み書き込みしたいので、この部分は独自実装してます)、もうモトローラ系は切り捨てていいのかな、Appleも製品として扱ってないようでしたし。画像読み書きはQuickTimeのフレームワークを使ってるのですが、このへん、また日記に書くことにします(初期化処理が新旧混在でややこしい部分です)。

Mac OS Xでのセマフォ(2008/10/13)

POSIXのセマフォ機能をMac OS Xで使えるのかチェック中。

http://www.linux.or.jp/JM/html/LDP_man-pages/man7/sem_overview.7.html

を参考にしてます。

「名前なしセマフォ」なんですが、sem_init()にて-1を返しますね。errnoを見ると「ENOSYS」が返ってます。サポートされてないようで(T_T)。

ということで「名前付きセマフォ」を確認。

sem_t *g_sem;
...
// 名前付きセマフォの作成
g_sem = sem_open("/tmp/hoehoe", O_CREAT, S_IRWXU, 0);
if(g_sem == SEM_FAILED) {
    // エラー!!
}

// 何か処理
// ...

// 名前付きセマフォの破棄
sem_close(g_sem);
sem_unlink("/tmp/hoehoe");

これでうまいこと動作しました。

これでWindowsでの「WaitForSingleObject」の動きはMacでも実装できそうです。後は「WaitForMultipleObjects」っぽいことをどうするか。sem_trywaitを複数分まわして判断するのが楽そうですね。

ちなみに、タイムアウトを指定しての「sem_timedwait」はMacではサポートされてないようでした(関数自体がないです)。

スレッドマスターの道は遠いですねぇ〜〜。UNIX系はmutexしかいじったことがなかったので(しかもかれこれ8年くらい前にちらっと)、このへんは新鮮ではあります。いやはや、このへんの仕組み、よくできてます。

Windowsでいう「CreateEvent」で作成するイベントハンドルでの「SetEvent」(シグナルの発行)はPOSIXの「sem_post」を使う、「WaitForSingleObject/WaitForMultipleObjects」はPOSIXの「sem_waitまたはsem_trywait」を使う、という置き換えになりそうです。

後、POSIXのsem_wait/sem_trywaitを呼んだタイミングで、sem_t構造体内のカウンタは減少するので、Windowsで言う「ResetEvent」は不要、ということですね。POSIXのほうが慣れるとスレッド管理は楽そうだなぁ。

Mac OS Xでのスレッド管理(2008/10/12)

Mac OS Xでのスレッド管理は、ThreadManagerを利用する方法やPOSIXを使用する方法がありますが、POSIXが割とわかりやすかったんで(というか、Linuxでも使えるので)いじってみました。

#include <pthread.h>

が必要です。

その際のTipsなど記載です。

ミリ秒単位のスリープ

/**
 * ミリ秒単位のスリープ
 * @param[in]  msec  時間待ちのミリ秒数
 */
void sleepMS(const int msec)
{
   struct timespec t;
   t.tv_sec = msec / 1000;
   t.tv_nsec = (msec % 1000) * 1000000;
	
   nanosleep(&t, NULL);
}

sleep関数は秒単位ですので、nanosleepを使います。usleepは過去のものだそうです。

スレッド関数

スレッドにて別処理される関数を用意します。関数は以下な感じ。中身はアプリ別で独自に実装のこと。

bool g_stopF = false;     ///< 終了確認フラグ 
bool g_busyF = false;    ///< スレッド稼働フラグ

/**
 * スレッドでの処理関数
*/
void *myThread(void *data)
{
    g_busyF = true;    // 実際はクリティカルセクションにて保護してフラグをたてること

    while(1) {
        if(g_stopF) break; // 何か終了条件

        // 何か処理
        // ....
  
        sleepMS(500);  // ウエイト(ここでは500ms)
    }
    g_busyF = false;  // 実際はクリティカルセクションにて保護してフラグをたてること
    return NULL;
}

スレッド停止関数

ここでは、例としてグローバル変数をフラグにしてますが、スレッドとバッティングする可能性があるため、値の取得・変更時は、mutex(WIndowsでのクリティカルセクション)で保護するようにします。

/**
 * スレッドの停止処理
 */
void threadStop()
{
    g_stopF = true;    // 実際はクリティカルセクションにて保護してフラグをたてること
    while(1) {
        if(!g_busyF) break;
        sleepMS(500);    // 500msのウエイト
    }
}

スレッドの作成と開始

pthread_attr_t attr;
pthread_t posixThreadID;
int threadErr;

pthread_attr_init(&attr); 
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
threadErr = pthread_create(&posixThreadID, &attr, &myThread, NULL);
pthread_attr_destroy(&attr);

if(threadErr) {
     // スレッドの作成に失敗
}

これでスレッド関数「myThread」が開始されます。メインスレッドではすぐに処理を返します。

スレッドの破棄処理

スレッドの終了は、スレッド関数myThread内で終了フラグをみて関数を抜ける、というのを前提としてそれが終わった後、メインスレッドにて以下を呼びます(いらないかもしれませんが、これを呼ばないとメモリリークする可能性あり。Appleのサイトのサンプルでは記載されてませんでした)。

pthread_detach(posixThreadID);
http://developer.apple.com/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/chapter_4_section_3.html

にて簡単な例があります。

後、メモリリークしているかの確認で

http://developer.apple.com/jp/technotes/tn2124.html

にていろいろ情報があります。

プログラム中にて

char commandStr[256];
sprintf(commandStr, "vmmap %d | grep \"shared pmap\"", getpid());

system(commandStr);

のようにすると、プロンプト上でなんか情報をゲットできますね(どれがメモリに関する情報かわからないので適当ですが)。vmmap/heap/malloc_history/leaksをみれば何かわかるかも。

mutex

主にグローバル変数の値を変更する場合、取得する場合の保護処理で使います。単純に、Windowsのクリティカルセクション相当の処理は

 // グローバル変数
 pthread_mutex_t g_mut = PTHREAD_MUTEX_INITIALIZER;

 // クリティカルセクション開始 
 pthread_mutex_lock(&g_mut);

 // 何か処理

// クリティカルセクション終了
 pthread_mutex_unlock(&g_mut);	

な感じ。以下のサイトを参考にしました。

http://www.linux.or.jp/JM/html/glibc-linuxthreads/man3/pthread_mutex_init.3.html

しかし、UNIX系のルールを使えるのは助かります。

Mac OS Xに関する覚え書き(2008/10/11)

普段はWindowsマシンにてプログラムするので、Macの当たり前に使うであろう機能を結構知らなかったりします。とりあえず、自分なりで「使えそう」というのをまとめてみました。

バックスラッシュの入力

[Option] + [\]

プログラムの改行にて「\n」としても認識しないですので,「\n」(Safariでは[option]+[\]も[\]も同じになっちゃいます)などの入力は必須。ちなみに、これを知らないときはバックスラッシュの部分だけコピペしてました(^_^;;。

「・」の入力

かなモード時に[Option]+[/]

Windows環境と異なるので。。。。みたいに「。。。」を打ってる例がある理由がわかったような(^_^;;

プログラムの強制終了

[command]+[option]+[esc]

Winでいうタスクマネージャらしきもの

アプリケーション/ユティリティ/アクティビティモニタ

ひらがなをカタカナに変換

かなモード時にMacBookの場合は[fn]+[F7]

たしか、デスクトップでは[F7]だけでいけてたような・・・。

かな入力時の半角ローマ字変換

上記と同じパターンですが、[fn]+[F8]。全角ローマ字の場合は[fn]+[f9]

FInderにて一つ上の階層に移動

[command]+[↑]

画面キャプチャ

  • [command]+[Shift]+[3] にてスクリーン全体をキャプチャ
  • [command]+[Shift]+[4] にて範囲選択にてキャプチャ
  • [command]+[Shift]+[4]+[Shift]にて、指定のウィンドウをクリックすると指定ウィンドウをキャプチャ

なお、キャプチャされた画像はデスクトップにpng形式にて保存される。

Winでいうペイントブラシみたいな機能

う〜ん、標準でないのか。ちょっとした作図にてよく使うのですが

http://paintbrush.sourceforge.net/

を入れてみました。

付箋紙

「Cellu It!」というのを入れてみました。

http://homepage.mac.com/sachiki/

また何か追加したら記載することにします。環境としてはFTPクライアントを探さなくては。

GDI+の画像読み込み(2008/10/05)

GDI+での画像読み込み(高速版)ですが、以前書いていたのに問題がありました。以下が正しい例ですが、bitmapData.Scan0に格納される1ライン分は4の倍数格納、というbmpの呪縛から抜け切れてないんですね。ですので、横が298ピクセル、という半端な数の場合では食い違いが起こってました。

Gdiplus::Bitmap *pBmp;
Gdiplus::BitmapData bitmapData;
RGBTRIPLE *pRGBPos;
unsigned char *pPos;
int scanBytes, x, y;

// 指定ファイルより画像を読み込み
pBmp = new Gdiplus::Bitmap(wFileName);
if(!pBmp) return false;

// 画像の幅と高さ
int wid = (int)(pBmp->GetWidth());
int hei = (int)(pBmp->GetHeight());

// 画像のRGB要素にダイレクトにアクセス
pBmp->LockBits(NULL, Gdiplus::ImageLockModeRead, PixelFormat24bppRGB, &bitmapData);

scanBytes = (int)bitmapData.Stride;     // = ((wid * 3) + 3) & 0ffffffc;
pPos      = (unsigned char *)bitmapData.Scan0;

// ピクセル情報を取得
for(y = 0; y < hei; y++) {
    pRGBPos = (RGBTRIPLE *)pPos;
    for(x = 0; x < wid; x++) {
        // Red要素は   pRGBPos->rgbtRed
        // Green要素は pRGBPos->rgbtGreen
        // Blue要素は  pRGBPos->rgbtBlue
        ... 何か処理
 
        pRGBPos++;
    }
    if(y + 1 >= hei) break;
    pPos += scanBytes;
}

// ロックの解除
pBmp->UnlockBits(&bitmapData);

delete pBmp;

しかし、今でもメモリアクセスは4の倍数のほうが速いのかなぁ。昔のPC-98時代は、4の倍数アクセスは鉄則だったのですが、現在でもなんか影響しそうかもしれない。SSEを使ったプログラムもたしかそんなのがありましたし(16倍数でのメモリ確保ってのもありましたね)。

MacBook(2008/10/04)

MacBookの一番グレードの低いのを買ってきました。最近まで名称はiBookかと思ってたのですが、MacBookなんですね。CoreDuoのノートPCです。これでMac移植ができるぜ〜、ということでwxWidgetsをビルド。サンプル等すんなり動作しました。

GUIはwxWidgetsに頼ってるのでOKっぽいんですが、今いじってるプログラムのコア部分はスレッドと文字列変換処理部がOS依存なものですので これを調査せねば。5年くらい前に使ってた文字列処理関数、そのまま使えるかなぁ。

Future's Laboratory 技術格納庫 2004-2013 Yutaka Yoshisaka.