Show page source of memo #68904

文章にまだまとめていないもの。

== プラットフォーム呼び出し メモ

・共用体を表現しようとしてLayoutKind::ExplicitとFieldOffsetを用いるときは、charをSystem::Byteにマッピングする。System::Charにするとwchar_tで2バイト使っているので、StructureToPtrで割り当て先不足(HRESULT: 0x8007007A)が発生する。

・「EventWaitHandle」とkernel32の「DeviceIoControl」を組み合わせて使わなくても、ksproxy.axの「KsSynchronousDeviceControl」を呼び出ししても同じ結果を得られた。パフォーマンスはどうだろう??

・MSDNの「FindFile のサンプル」で示されているような構造体の平坦化はしない。StructLayoutを指定している構造体をネストする分にはマーシャリングはきちんとされる。


== VST Host メモ

・VSTiの呼び出し規約はcdecl

・VSTiをロードしたらVSTiのスレッドが生み出されている可能性がある為、effOpenしていなくても、effCloseを呼び出してからアンロードする(VSTi側の造りに依るとは思う)

・プラグインの中には「kVstMax~」の制限に従っていないものもあるので、受けるバッファは大きめで取っておかないといけない(とかどうしようもない)

・AEffectDispatcherProcの戻り値もプラグインによってバラバラなので、戻り値は参考にできない(成功値が0だったり1だったりいろいろ)

== あまり参考にしてはならないモノ

・ドライバにメモリブロックを参照させるときは、GlobalAllocで確保して、GlobalLockでスワップさせないようにしなければならない、、、とセオリーで考えていたけども、LocalAlloc(≒bittable型のarrayをpinで止めたモノ)でも動いてしまっている。
考えが16bit時代で止まってしまっているかしら。
しばらくLocalAllocで進めるが、どこかで問題が起きるかもしれないので注意しておく。

・waveOutOpenでコールバックをFUNCTIONにしていて、waveOutWriteからのWOM_DONEがコールバックされた時は、コールバック関数中にwaveOutUnprepareHeaderを呼び出しても大丈夫だが、waveOutResetからのWOM_DONEがコールバックされた時にwaveOutUnprepareHeaderを呼び出すとデッドロックする。
ドライバに依るかもしれないが、そもそもMSDNでも呼び出し禁止になっているので、waveOutUnprepareHeaderはいずれの場合もコールバック関数の外で呼び出さないとダメ。

・構造体のtypedefを継承で置き換えると、System::Runtime::InteropServices::Marshal::SizeOfの返り値が1バイト増える。


== System::Tupleをジェネリック関数の戻り値に使うと、C2440エラーが出る場合がある。

{{{
次の環境での現象
Microsoft Visual Studio 2010
Version 10.0.30319.1 RTMRel
Microsoft .NET Framework
Version 4.0.30319 RTMRel
}}}

あまりやらないコードなのかもしれないが、必要になったので定義したところ、下記はコンパイルエラーになってしまう。

{{{ code cpp
ref class A {
  generic<typename OUT>
  System::Tuple<OUT>^ method1(int b) {
    OUT d;
    return gcnew System::Tuple<OUT>(d); // error C2440: 'return' : 'System::Tuple<T1> ^' から 'System::Tuple<T1> ^' に変換できません。
  }

  generic<typename OUT>
  System::Tuple<OUT>^ method2(int b, int c) {
    OUT d;
    return gcnew System::Tuple<OUT>(d); // error C2440: 'return' : 'System::Tuple<T1> ^' から 'System::Tuple<T1> ^' に変換できません。
  }
};
}}}

但し、ジェネリックメソッドを1つだけ定義している場合、

{{{ code cpp
ref class A {
  generic<typename OUT>
  System::Tuple<OUT>^ method1(int b) {
    OUT d;
    return gcnew System::Tuple<OUT>(d);
  }
};
}}}

ジェネリックの型指定の数が異なる場合、

{{{ code cpp
ref class A {
  generic<typename OUT>
  System::Tuple<OUT>^ method1(int b) {
    OUT d;
    return gcnew System::Tuple<OUT>(d);
  }

  generic<typename IN, typename OUT>
  System::Tuple<OUT>^ method2(IN b) {
    OUT d;
    return gcnew System::Tuple<OUT>(d);
  }
};
}}}

ジェネリック関数ではなく、ジェネリッククラスとしている場合はコンパイルが通る。

{{{ code cpp
generic<typename OUT>
ref class A {
  System::Tuple<OUT>^ method1(int b) {
    OUT d;
    return gcnew System::Tuple<OUT>(d);
  }

  System::Tuple<OUT>^ method2(int b, int c) {
    OUT d;
    return gcnew System::Tuple<OUT>(d);
  }
};
}}}

また、適当なTupleを自前で用意した場合も、コンパイルが通る。

{{{ code cpp
ref class A {
  generic<typename OUT>
  ref class Tuple {
  public:
    OUT t;
    Tuple(OUT v): t(v) {};
  };

  generic<typename OUT>
  Tuple<OUT>^ method1(int b) {
    OUT d;
    return gcnew Tuple<OUT>(d);
  }
		
  generic<typename OUT>
  Tuple<OUT>^ method2(int b, int c) {
    OUT d;
    return gcnew Tuple<OUT>(d);
  }
};
}}}