none
midiOutOpenができません RRS feed

  • 質問

  • 初めて質問させていただきます。

    当方、C/C++はかじったことがあるのですがVisual C++は初心者です。

    Windows Vista Home Premium で Visual C++ Express Edition を使用しています。

     

    Form1でピアノの鍵盤のような画面を作り、鍵盤をクリックすると音が鳴る、というものを作っているところなのですが、

    midiOutOpen()の戻り値が「MMSYSERR_INVALPARAM 指定されたポインタまたは構造体は無効です。」となり、

    音が出ません。

     

    ググってみると、midiOutOpen()の第一引数は「HMIDIOUT型へのポインタ」となっているものと、

    「LPHMIDIOUT型」となっているものと、両方出てくるので(この2つは同じ意味なのでしょうか?)両方試してみたところ、

    以下のようになりました。

     

    前者のケース↓

    //変数宣言

    HMIDIOUT hMidiOut;

    (略)

    //MIDIオープン

    int ret;  //midiOutOpen関数の戻り値

    ret = midiOutOpen(&hMidiOut,-1,0,0,0);

    //↑ または ret = midiOutOpen(this->hMidiOut,-1,0,0,0);

    [コンパイルエラー]

    error C2664: 'midiOutOpen' : 1 番目の引数を 'HMIDIOUT' から 'LPHMIDIOUT' に変換できません。(新しい機能 ; ヘルプを参照)
    指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。

     

    後者のケース↓

    //変数宣言

    LPHMIDIOUT lphMidiOut;

    (略)

    //MIDIオープン

    int ret;  //midiOutOpen関数の戻り値

    ret = midiOutOpen(lphMidiOut,-1,0,0,0);

    [結果]

    コンパイルは通るが、ret=11=MMSYSERR_INVALPARAM (指定されたポインタまたは構造体は無効)になる

     

    ちなみにまったく同じプログラムをVisual Vasic 2005(こちらはExpress Editionではなく正規版です)で作ったところ、

    問題なく音が鳴りました。

     

    どうすればmidiOutOpen が正常にできるのか、教えて頂ければ幸いです。

    宜しくお願い致します。

    長文失礼致しました。

     

     

    2008年2月8日 3:18

回答

  •  yu_taki さんからの引用

    ret = midiOutOpen(&hMidiOut,-1,0,0,0); と書いたとき↓

    [コンパイルエラー]

    error C2664: 'midiOutOpen' : 1 番目の引数を 'cli::interior_ptr<Type>' から 'LPHMIDIOUT' に変換できません

    hMidiOutをrefクラスのメンバ変数にしていませんか?(たとえばForm1のメンバ変数とか)

    (メンバ変数なら m_hMidiOut とか hMidiOut_ とかわかるようにしてもらいたいです。)

     

    pin_ptrを使ってピン止めしてあげてから渡すとどうなりますか?

    以下実験したコード

    Sample
    #include <windows.h>
    
    // 実験用関数
    void __stdcall Hoge(LPHMIDIOUT l)
    {
        *l = (HMIDIOUT)0x1;    // 値が設定されたか確認用
    }
    
    value struct AAA { HMIDIOUT hMidiOut; };
    ref struct BBB { HMIDIOUT hMidiOut; };
    
    int main()
    {
        // ローカル変数
        HMIDIOUT hMidiOut = NULL;
        Hoge(&hMidiOut);
    
        // valueクラスのメンバ
        AAA a;
        a.hMidiOut = NULL;
        Hoge(&a.hMidiOut);
    
        // refクラスのメンバ
        BBB b;
        b.hMidiOut = NULL;
        // Hoge(&b.hMidiOut); C2664
        pin_ptr<HMIDIOUT> p = &b.hMidiOut;
        Hoge(p);
    
        return 0;
    }
    2008年2月12日 18:06

すべての返信

  •  > ちなみにまったく同じプログラムをVisual Vasic 2005(こちらはExpress Editionではなく正規版です)で作ったところ、

     > 問題なく音が鳴りました。


    Visual Studio 2005?(Std/ProのC++?)
    Visual Basic 2005?(Std/Pro)

    midiOutOpenってWin32 APIの関数ですよね?
    Platform SDKがインストールされていないんじゃないですかね。
    Express Editionでダメってことなら。

    http://www.cppdrive.jp/vc/sdk/
    http://freepg.fc2web.com/cpp/topic_vce_001.html
    2008年2月8日 4:45

  • と、書いたものの、ビルドできてる時点でSDKもインストールされてる気がしますね・・・。
    (DLLとかライブラリが足りない、壊れている、などあるかもしれませんが。)

    Express版 と 上位版でビルドした実行ファイルは同じPCで実行されているんでしょうか?
    VistaはMIDI Mapperがなくなったとかって情報も見かけますが再生環境は大丈夫ですか?
    2008年2月8日 5:26
  • >ぼーずさん

     

    さっそくの回答ありがとうございます。

    スペルミス、、、(笑)すみません。

    Visual Studio 2005 の Visual Basic です。

    ビルド、実行ともにまったく同一のPCでやりました。

     

    先ほど、Visual Studio 2005 (正規版)の中のC++でビルドしてみたところ、

    やはりmidiOutOpenの戻り値が11になってしまいました。

    (ややこしくなってすみません。現在、同じPCの中に、

      ・VB(正規版)でビルドしたもの:音が出る

      ・VC++(正規版)でビルドしたもの:音が出ない

      ・VC++(Express Edition)ででビルドしたもの:音が出ない

    の、3つがあることになります。VC++の2つは同一のプロジェクトを正規版とExpressの双方から開いたものです)

    winmm.libはリンク済みです。

     

    SDKはまだ確認していないのですが、調べてまた書き込みます。

    取り急ぎ失礼します。

    2008年2月8日 6:32
  • 上位エディションでビルドしても同じ結果ならSDKは関係ないので気にしないでください。

    2008年2月8日 7:59

  • 前者のケースがコンパイルが通らないのってのがおかしいですね。
    後者のケースは間違いです。
    実体がないポインターを渡しているのでMMSYSERR_INVALPARAMになります。

    これ、コンパイル通ったコードをそのまま貼り付けてます。
    HMIDIOUT hMidiOut;
    int ret = midiOutOpen(&hMidiOut,-1,0,0,0);



    「1 番目の引数を 'HMIDIOUT' から 'LPHMIDIOUT' に変換できません。」
    ってエラーからして、単に参照演算子(&)をつけ忘れてたんじゃないかと思うのですが。

    ○: 
    &hMidiOut
    ×: hMidiOut
    2008年2月8日 8:37
  • >ぼーずさん

    書き込み有難うございます。ここ数日ネットに接続できない環境におりまして、レスが遅れてすみませんでした。

     

    試しに、「&hMidiOut」と「hMidiOut」両方でコンパイルしてみました。

    以下のようになりました。

     

    ret = midiOutOpen(&hMidiOut,-1,0,0,0); と書いたとき↓

    [コンパイルエラー]

    error C2664: 'midiOutOpen' : 1 番目の引数を 'cli::interior_ptr<Type>' から 'LPHMIDIOUT' に変換できません

     

    ret = midiOutOpen(hMidiOut,-1,0,0,0); と書いたとき↓

    [コンパイルエラー]

    error C2664: 'midiOutOpen' : 1 番目の引数を 'HMIDIOUT' から 'LPHMIDIOUT' に変換できません

     

    今日気づいて気になったのですが、winmm.libはリンク済み、と書きましたが、

    後者のケースでコンパイルが通る場合、デバッグ時の出力に

    「~が読み込まれました。シンボルは読み込まれませんでした。」と表示される中に、

    「~winmm.dllが読み込まれました。」とは出てこないのです。。。

    うまくリンクできていないということなのでしょうか???

    2008年2月12日 7:53
  •  yu_taki さんからの引用

    ret = midiOutOpen(&hMidiOut,-1,0,0,0); と書いたとき↓

    [コンパイルエラー]

    error C2664: 'midiOutOpen' : 1 番目の引数を 'cli::interior_ptr<Type>' から 'LPHMIDIOUT' に変換できません

    hMidiOutをrefクラスのメンバ変数にしていませんか?(たとえばForm1のメンバ変数とか)

    (メンバ変数なら m_hMidiOut とか hMidiOut_ とかわかるようにしてもらいたいです。)

     

    pin_ptrを使ってピン止めしてあげてから渡すとどうなりますか?

    以下実験したコード

    Sample
    #include <windows.h>
    
    // 実験用関数
    void __stdcall Hoge(LPHMIDIOUT l)
    {
        *l = (HMIDIOUT)0x1;    // 値が設定されたか確認用
    }
    
    value struct AAA { HMIDIOUT hMidiOut; };
    ref struct BBB { HMIDIOUT hMidiOut; };
    
    int main()
    {
        // ローカル変数
        HMIDIOUT hMidiOut = NULL;
        Hoge(&hMidiOut);
    
        // valueクラスのメンバ
        AAA a;
        a.hMidiOut = NULL;
        Hoge(&a.hMidiOut);
    
        // refクラスのメンバ
        BBB b;
        b.hMidiOut = NULL;
        // Hoge(&b.hMidiOut); C2664
        pin_ptr<HMIDIOUT> p = &b.hMidiOut;
        Hoge(p);
    
        return 0;
    }
    2008年2月12日 18:06
  • >蒼の洞窟さん

    書き込み有難うございます。

     

    hMidiOutはForm1のメンバ変数でした。

    refクラス、というのがいまひとつ理解できていなかったもので。。

     

    pin_ptr<HMIDIOUT> p = &hMidiOut;
    ret = midiOutOpen(p,-1,0,0,0);

    で、見事ret=0になり、音を出すことができました。有難うございます!

     

    またお世話になることがあるかと思いますので、

    そのときには宜しくお願い致します。

     

     

    2008年2月13日 7:32