インスタンスメソッドを関数ポインタとして渡す方法


枕元  2008-11-09 05:18:49  No: 69215

C++/CLIで開発しています。

下記の①のようなプログラムを書いたところ、
「error C2276 仮想関数のアドレスを取ろうとしました」
とのエラーが表示されました。
そこで、↓を読み、
http://msdn.microsoft.com/ja-jp/library/850cstw1(VS.80).aspx
structA ss = &this->testMethod;
の部分を
structA ss = {&A::testMethod};
に直しましたが、今度は、
「error C3374 delegate インスタンスを作成する場合以外に、A::testMethodのアドレスをしていできません」
とエラー表示が表れました。
そこで、↓を読み、
http://msdn.microsoft.com/ja-jp/library/5408cs95(VS.80).aspx
下記②のようにdelegateを利用する仕様にしましたが、今度は
「error C2440 初期化中 A::Fnc^ からvoid(__cdecl *)(void)に変換できません」
という旨のエラーが出てきました。

当方、C++については理解が足らず、もしかしたら極めて初歩的な問題かもしれませんが、どうにも手詰まりとなってしまいました。
解決方法をご存じな方がいらっしゃいましたらお教え願えないかと思っております。
どうぞよろしくお願いいたします。

//①*****************************************************
public struct structA
{
  void (* f) ();
};

ref class A
{
private:
  void testMethod(){}

  void setTestMethod(){
    structA ss = &this->testMethod;
  }
};
//*****************************************************

//②*****************************************************
public struct structA
{
  void (* f) ();
};

ref class A
{
private:
  void testMethod(){}

  void setTestMethod(){
    Fnc ^ fnc = gcnew Fnc(this, &A::testMethod);
    structA ss = {fnc};
  }

  delegate void Fnc();
};
//*****************************************************


Blue  2008-11-10 09:49:20  No: 69216

>public struct structA
>{
>  void (* f) ();
>};
を変更しないとどうしようも出来ません。
(あるクラスの(staticではない)メンバ関数を割り当てることは不可能です。)

public delegate void Func();
public ref struct structA
{
    Func^ f;
};
public ref class classA
{
private:
    void testMethod() {}
    void setTestMethod()
    {
        structA ss;
        ss.f = gcnew Func(this, &classA::testMethod);
    }
};


Blue  2008-11-10 10:11:04  No: 69217

試したところ、Marshal::GetFunctionPointerForDelegateを使えば
メンバ変数もできるっぽいです。

using namespace WindowsApplication;
using namespace System::Runtime::InteropServices;

struct structA
{
    void (*f)();
};

public ref class classA
{
    int n;
    void func() { MessageBox::Show(n.ToString()); }
    delegate void Func();
public:
    void test()
    {
        structA s;
        n = 10;
        Func^ f = gcnew Func(this, &classA::func);
        IntPtr p = Marshal::GetFunctionPointerForDelegate(f);
        s.f = static_cast<void (*)()>(p.ToPointer());
        
        // 実験
        (*s.f)();

    }
};


Blue  2008-11-10 10:39:32  No: 69218

連投ですが、
http://msdn.microsoft.com/ja-jp/library/367eeye0(VS.80).aspx
をみるとやはりGCHandle::Allocをあわせて使うのが正しいそうです。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加