トップページ⇒tech
26コメント11KB

コールバックを展開したい

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。 NGNG
具体的にはwaveInOpen/waveOutOpenの低レベルオーディオは
コールバックで入出力が呼び出されるのですが、
ファイル入出力と同じように扱えるようにしたいのです。
やっぱりコルーチンですかねえ。

まあファイル入出力の方をコールバックで処理するようにすれば
同一性は保てるのですが・・・・・一般的じゃないですよね
00021 NGNG
ただ、コールバックで呼び出された時にスタックを切り替えてreturnした場合
スレッドはどのスレッドで実行されてる事になるの? とか考え出して混乱して来ました

たとえば、入出力する為のスレッドを作って処理させている場合最初にWaveInOpen
とかした時のスレッドになるのかな? でも、ウインドへのメッセージでも処理出来る
から、その場合はメッセージはメインスレッドで処理されてますよね?
なんかおかしいなあ
00031 NGNG
ヘルプの説明では
>NTでは、 低レベル コールバック関数は個々のスレッドごとに呼び出される
>NTにおいても、 できるだけ同じAPIセットの低レベル オーディオ コールバック関数を使うようにしてください
というのがあるので怪しい感じだけど、試しにやってみます
0004名無しさん@お腹いっぱい。 NGNG
2時間悩んだらしいな、ほめてつかわす。
0005名無しさん@お腹いっぱい。 NGNG
オールバック(謎
0006名無しさん@お腹いっぱい。 NGNG
ところで マルチメディア系のAPIではWin32でも GlobalLockとか要求してるけど
これって必要なの? またこれって何やってるの?
0007>>6 NGNG
よく判らん。確かにGMEM_FIXEDなら直接メモリが得られるのにね。
まあVCL使ってるから GlobalReAllocPtr使ってるから不便じゃないよ

無ければ GlobalAlloc と GlobalLockをペアにして呼び出す関数作ればいい
 サンプルみたいにいちいちallocでチェックlockでチェックとしなくても
 連続して呼んだ後でエラーチェックすればいい

開放する時は GlobalHandle/GlobalUnlock/GlobalFreeの順に呼べばいい
00086>7 NGNG
レスありがとうございます。
こんな感じですかね
void* GlobalAllocPtr( UINT fuFlags@` /* オブジェクト割り当て属性 */
           DWORD cbBytes) /* 割り当てるバイト数    */
{
return GlobalLock( GlobalAlloc( fuFlags@`cbBytes ) );
}

BOOL GlobalFreePtr( void *mem ) /* エラーなら0が帰る */
{ HGLOBAL hglbMem= GlobalHandle(mem);
  BOOL  noterr = GlobalUnlock(hglbMem) ;
 return noterr & ( GlobalFree(hglbMem) == NULL );
}
0009ビル・ジョブス NGNG
>8
エラーチェックしなちゃい!
さらに、GlobalAlloc()のフラグまで引数にするなら、こうしたほうが良い。
GMEM_FIXEDで確保してGlobalLock()しても間違いじゃないケド...無駄。
LPVOID GlobalAllocPtr(UINT fuFlags@` DWORD cbBytes)
{
  HGLOBAL hgTemp = GlobalAlloc(fuFlags@` cbBytes);
  if (!hgTemp) return (LPVOID)NULL;
  if (fuFlags & GMEM_FIXED)
    return (LPVOID)hgTemp;
  else
    return GlobalLock(hgTemp);
}

なぜGlobalLock()が必要かって?いい質問だ。
GMEM_MOVEABLEでGlobalAlloc()されたメモリは、GlobalAlloc()
しないとアクセスできないんだよ!それは分かってるか?
なぜなら、GlobalAlloc()した時点で領域は確保されているが
どこに確保されているかは不定なんだ、だから戻り値はハンドルだ。
ポインタじゃない。なぜそうしているかって?
それは、GlobalLock()されていないメモリはアクセスできないから
他に優先して仮想記憶に追い込めるだろ。
意味が分からなければまた来いよ。ベイベー!
0010ビル・ジョブス NGNG
#9
間違えたぞ〜!

誤)GMEM_MOVEABLEでGlobalAlloc()されたメモリは、GlobalAlloc()
正)GMEM_MOVEABLEでGlobalAlloc()されたメモリは、GlobalLock()
0011名無しさん@お腹いっぱい。 NGNG
>9

>それは、GlobalLock()されていないメモリはアクセスできないから
>他に優先して仮想記憶に追い込めるだろ。

また間違ってるよ。WIN16のメモリ管理方法とページングの
仕組みについて勉強してね。
00127>>10 NGNG
いや私がVCLではエラーチェックしてないから必要無いだろと書いたからでしょう
実際、最初のエラーでNULLが帰れば GlobalLockもエラーを返しますからね
まあ転ばぬ先の杖でエラーチェックする方が良い事は否定しません。
でも、通常は成功する事の方が多いですし、この場合片方だけが成功しても意味
がありませんから私は途中のチェックを省略する方が好きです。
8さんはチェックしていますがVCLではGlobalHandle/GlobalUnlock/GlobalFree
間でもエラーチェックしていません。正しく管理されたならこの間にエラーが出る
筈が無いからです。

Lockにちては、実際、何故要求されるのかは良く判りませんね。
デバイスが割込み中にアクセスする為にメモリの属性を変化させる
必要があるのだとしたら、最初からファイルマップを要求するか
システムがメモリを用意すれば良さそうに思います。
たぶん単純にWin3.1との互換性の為じゃないかなあ
0013>6 NGNG
>ところで マルチメディア系のAPIではWin32でも GlobalLockとか要求してるけど
要求ってよくわからないので、具体的な関数(GlobalLockを要求してる)の名前きぼ。
0014>13 NGNG
?
ローレベル系にある xxxPrepareHeaderヘルプをひいてみたら?
   例:midiInPrepareHeader
あと、mmio操作でも・・・・

 ReadFile操作とかには無いのにね
0015ビル・ジョブス NGNG
>11
なんでWIN16?
WIN16とWIN32じゃメモリ管理違うんだけど...
何を言いたいのでしゅか?反論があるなら具体的に言ってね!
ちみはいつも煽るだけでしゅね!
おまえ、さみしいヤツだな...同情するよ。
001613>14 NGNG
そのmidiInPrepareHeaderのヘルプを見てみたんだけど、
midiInUnprepareHeaderを呼ぶまでバッファを変えたり
開放したりするなとは書いてあったけどGlobalLockに関
する記述は見当たらないので…

「GlobalLockを要求」っていうのが解りません。
おしえてください。お願いします。
0017>>16 NGNG
あ、ホントだ。
SDKの英語ヘルプのMMprogrammerリファレンス見たら記述がない。

でも日本語ヘルプ(Win32 API プログラマーズリファレンス)にはしっかりと
>備考
>MIDIHDR構造体とそのlpDataメンバが指すデータ ブロックは、
> GlobalAlloc関数にGMEM_MOVEABLEフラグやGMEM_SHAREフラグを
>指定して割り当てて、 GlobalLock関数でロックします

うーん。Win32では無理にいちちGlobalAlloc/Lockしなくてもいいのかな?
と思いつつヘルプのサンプルコードは同じだ(Alloc/Lockしてる)からなあ
001817 NGNG
こういうのは厄介だなあ。英語ヘルプにやれとは書いてないけど
やらなくていいとも書いてない。
理屈から考えても、たぶんやらなくていいのが正解だと思うんだけど、
でも、サンプル通りにしないと後でどうなるやら判らないしなあ・・・
まあ個別にAlloc/Lockする手間は最初に1回やればいいんだから今まで
通りしとこう。

あ、mmioOpenの方にはなんか書いてあるけど詳しくは読んでないのでパス
0019名無しさん@お腹いっぱい。 NGNG
16>17
どうもです。mmioOpen見てみましたが、どうも、メモリブロックのサイズ
を変える時にGlobalReAlloc使うから、adwInfoに拡張するサイズを入れる
時にはGlobalLockって書いてある感じですね。(えいご、不得手なもんで)
API側で受け取ったメモリブロックのサイズいぢる場合は、こうしないと
どうしようも無いから、これはこれで納得したような、しないような。
002017>19 NGNG
ごめん。WavファイルはWin以外からも読みたかったから直接読み書きする
自作ライブラリでやってるもんだから mmioについて詳しい事は調べてない。
とまあ、言ってる事とやってる事がチグハグなんだけどね(^^;
いわゆる一旦動いたら後、冒険はしたくないタチって奴だ(^^;

で、1さんが上手くゆくかどうか結果を楽しみにしてるんだけどね。
0021名無しさん@お腹いっぱい。 NGNG
>1
変な小細工しないで、CALLBACK_EVENTを使ったら?
002217>>21 NGNG
いや、だからOOの為にファイル入出力と同じ体系で扱えるようにしたいんでしょう
1さんもファイル入出力の方をコールバック式にするのが簡単だというの
は判ってるみたい。
実際自分はそうしてるけど、それは結構面倒な面も多いんだよね。
コルーチンで展開出来たら美味しいよなあ
0023名無しさん@お腹いっぱい。 NGNG
>22
CALLBACK_EVENTはコールバックじゃないよ。
002417>>23 NGNG
ああ、同期を使ってやれという事ですか?
 CALLBACK_THREAD てのもありますよね。
でも、サンプルが無いので使い方不明。どっかに解説ありません?

具体的にはどうやって使いおわったヘッダを渡すのかとか
まあ順番に使われるから判るだろというのはあるけど、想像で使うのは恐そう
0025>24 NGNG
23さんじゃありませんが CALLBACK_THREADの場合は
GetMessageで窓へのメッセージと同じように受信したと思います

Win3.1の頃はCALLBACL_FUNCじゃないと使い物にならないほど遅かったので
CALLBACK_FUNCTIONしか使わない人も多いですね。
・・・・実際はどれも遅いけど
002617>>24 NGNG
なるほど、それなら簡単かも
■ このスレッドは過去ログ倉庫に格納されています