none
void * の引数の渡し方について

    質問

  • 以下、勉強しているあるメーカーのMFCの例題になります。

    void CTestDlg::Init()
    {
    SetCallbackChanged(・・・, this, &CTestDlgDlg::CallBackChanged); // callback event のセット
    }

    void CTestDlg::CallBackChanged(・・・, ・・・, void *pvContext)
    {
    CTestDlg *pDlg = reinterpret_cast<CMultiCameraDlg *>(pvContext);
    // 以下、pDlgを使って処理
    }
    正常に動いています。
    this, void *pvContext でダイアログのメンバー変数の全てを渡しているのだと思います。


    私が作っているのは MFCのDLLですが、全てグローバルな関数になります。
    上記のように複数の変数を渡したいと思い以下のように色々していますが、
    引数が上手く渡せません。
    (1つの引数なら渡せていますし、コールバック関数としては上手く動いています。)

    struct TEST_CALLBACK_ARG {
    int ID;
    int Size;
    };

    void Init()
    {
    TEST_CALLBACK_ARG pvContext;
    pvContext.ID = 3;
    pvContext.Size = 1000;
    SetCallbackChanged(・・・, &pvContext, &CallBackChanged); // callback event のセット
    }

    void CALLBACK CallbackChanged(・・・, ・・・, void *pvContext)
    {
    TEST_CALLBACK_ARG *pContext = reinterpret_cast<TEST_CALLBACK_ARG *>(pvContext);
    int ID = pContext->ID;
    int Size = pContext->Size;
    }

    質問のタイトルが適切ではないかも知れませんが、よろしくお願いします。



    mnicksashimisan

    2018年9月26日 6:34

回答

  • 関数 void Init() {/*** 省略 ***/} の中で型 TEST_CALLBACK_ARG の自動変数(オート変数) pvContext を宣言、定義しています。そして、これをコールバックと思われる CallbackChanged() 関数に引数として &pvContext として渡していますが、これがどういうことなのか分かった上でこうなさっているのでしょうか?

    関数 Init() が終わったら、自動変数 pvContext はいなくなります。なので、関数 CallbackChanged() には幻の変数へのポインターを渡していることになります。これが引数がうまく渡らない原因かもしれません。 コールバック関数に渡した直後には残骸が残っていてもそのうち、値が壊れているのでしょう。

    中澤@失業者さんも仰っていますが、貴方の事情(どこが判らないのか、どのようなプログラムを書いているのか)を知らない他人が読むのですから

    >引数がうまく渡せません

    >(1つの引数なら渡せていますし、コールバック関数としては上手く動いています。)

    といった内容が読取れない--あなたにしか判らない--書き方は困ります。

    後、余計なことかもしれませんが、変数名が p で始まるものは C/C++ では伝統的にポインターであることを示すので pvContext という名前はあなたの例では余計な混乱の元になりかねないと感じました。少なくとも私はポインターでもないのに何で p で始めるんだろうと気になりました。

    2018年9月26日 8:11

すべての返信

  • 一見すると、同じ関数SetCallbackChanged()に、異なる型の引数を渡そうとしているように見えます。
    まず、どのように「うまくいかない」のか明記すべきです。
    そうでないと役に立つ回答が得られないと考えられます。

    (例)
    1.コンパイルエラーになる。(エラーをコピペしましょう)
    2.リンクエラーになる。(エラーをコピペしましょう)
    3.実行時に障害が発生する。(発生内容を記述します)
    4.漢字の「・・・」は省略記号だと思いますが、可能なら明示してください。

    最後に、SetCallbackChanged()関数はWin32SDK、MFC、C言語ランタイムLib、STL等に含まれません。
    この関数はCallBackChanged()をコールバックするのだろうと想像はできますがその他はまるでわかりません。
    他人作ならプロトタイプと仕様を、自作の場合は左記に加えて実装を掲載してみてください。
    2018年9月26日 7:27
  • 関数 void Init() {/*** 省略 ***/} の中で型 TEST_CALLBACK_ARG の自動変数(オート変数) pvContext を宣言、定義しています。そして、これをコールバックと思われる CallbackChanged() 関数に引数として &pvContext として渡していますが、これがどういうことなのか分かった上でこうなさっているのでしょうか?

    関数 Init() が終わったら、自動変数 pvContext はいなくなります。なので、関数 CallbackChanged() には幻の変数へのポインターを渡していることになります。これが引数がうまく渡らない原因かもしれません。 コールバック関数に渡した直後には残骸が残っていてもそのうち、値が壊れているのでしょう。

    中澤@失業者さんも仰っていますが、貴方の事情(どこが判らないのか、どのようなプログラムを書いているのか)を知らない他人が読むのですから

    >引数がうまく渡せません

    >(1つの引数なら渡せていますし、コールバック関数としては上手く動いています。)

    といった内容が読取れない--あなたにしか判らない--書き方は困ります。

    後、余計なことかもしれませんが、変数名が p で始まるものは C/C++ では伝統的にポインターであることを示すので pvContext という名前はあなたの例では余計な混乱の元になりかねないと感じました。少なくとも私はポインターでもないのに何で p で始めるんだろうと気になりました。

    2018年9月26日 8:11
  • > 関数 Init() が終わったら、自動変数 pvContext はいなくなります。

    > なので、関数 CallbackChanged() には幻の変数へのポインターを渡していることになります。
    > これが引数がうまく渡らない原因かもしれません。
    グローバル変数にしたら、正しい値が渡るようになりました。

    コールバックのやり方も、void * で引数を渡すやり方も不慣れで、
    pvContext 等の書き方はメーカの例題のままになります。
    SetCallbackChanged()はメーカが用意した関数になります。
    コールバックは一般的にこういうやり方をするのだと思いながら、
    &pvContext の使い方は想像しながらやっているところです。

    SetCallbackChanged()でpvContextのアドレスを登録しているので、
    ローカル変数で良いものと思っていましたが、そうではなかったようです。



    mnicksashimisan

    2018年9月26日 9:05
  • C/C++ の経験が少ない状態で進められているようにお見受けします。
    ちょっとしたプログラムであれば、そのまま進めても問題ないかもしれませんが、これから大がかりなものを作ろうという場合は、C/C++ 経験者をそばに置いた方が良いと思います。

    C/C++ はその論理を理解していないと、コンパイルは通っても時々落ちるなど、調査困難な不具合を多数発生させる可能性があるためです。

    2018年9月26日 13:09
    モデレータ