0

Cの古いコードを現在のVC++プロジェクトに結合しようとしています。

// .h
    class DMSinv : public CDialog {
        double finte(double z);
        double ITFStolz(double Zp1, double Zp2, double Zc);
    };

// .cpp
    double Zcglob;
    double DMSinv::finte(double z) 
    {
       return TFStolz(z, Zcglob);
    }

    double DMSinv::ITFStolz(double Zp1, double Zp2, double Zc)
    {
        int ierr;
        Zcglob = Zc;

        return (coteglob(&DMSinv::finte, Zp1, Zp2, 1.0e-10, &ierr));
    //error C2664: 'DMSinv::coteglob' : cannot convert parameter 1 from 'double (__thiscall DMSinv::* )(double)' to 'double (__cdecl *)(double)'    

    }

coteglob関数は古いC部分に由来し、finteはTFStolz関数をcoteglobに渡すための中間関数です。

私はフォーラムを検索し、この関連する質問を見つけました: void(__thiscall MyClass :: *)(void *)を この方法で適用しようとしたvoid(__cdecl *)(void *)ポインターに変換する方法:

// .h
    class DMSinv : public CDialog {
        virtual double finte(double z);
        double ITFStolz(double Zp1, double Zp2, double Zc);
    };

// .cpp
    double Zcglob;
    extern "C"
    {
        static double __cdecl finteHelper(double z)
        {
            DMSinv* datainv = reinterpret_cast< DMSinv > (z); //error C2440: 'reinterpret_cast' : cannot convert from 'double' to 'DMSinv'  

            datainv->finte(z);
        }
    }

    double DMSinv::ITFStolz(double Zp1, double Zp2, double Zc)
    {
        int ierr;
        Zcglob = Zc;
        double solution = coteglob(&finteHelper, Zp1, Zp2, 1.0e-10, &ierr);
        return solution;
    }

しかし、まだ機能していません。誰かがそれを適応させる方法について私を導くことができますか?私はまだかなりの初心者であり、これは私の知識からはほど遠いようです。

前もって感謝します!

4

2 に答える 2

0

私はあなたがこのようにそれをすることができるとは思わない。どういうわけか、オブジェクトへの参照を渡す必要があります(this)。リンクされた質問では、関数へのパラメーターは型として定義されていたvoid *ため、へのポインターを含め、必要なものはすべて関数に渡すことができましたthis。あなたの関数はを受け入れるdoubleので、あなたはそれに渡すことができませんthis

クラスの内部から独立しているように見えるので、クラス外で中間関数を定義するのが最も簡単だと思います。このようなもの:

double finte(double z) 
{
   return TFStolz(z, Zcglob);
}

インスタンスポインタを、静的関数が読み取ることができるパブリックグローバル/静的クラス内変数に格納することもできます。

于 2013-03-27T12:19:56.103 に答える
0

あなたが望むようにそれが可能かどうかわからない。私の頭に浮かぶ唯一のオプションは、静的変数を使用してDMSinvオブジェクトのアドレスを格納することです。これにより、簡単な実装で1つのスレッドに制限されます...

これを試して:

// .h
class DMSinv : public CDialog {
    double finte(double z);
    double ITFStolz(double Zp1, double Zp2, double Zc);

private:
  static DMSinv* _current;
  static double __cdecl finteHelper(double z);
};

// .cpp
double Zcglob;
DMSinv* DMSinv::_current = 0;
double DMSinv::finte(double z) 
{
   return TFStolz(z, Zcglob);
}

double DMSinv::ITFStolz(double Zp1, double Zp2, double Zc)
{
    int ierr;
    Zcglob = Zc;

   _current = this;
   return (coteglob(DMSinv::finteHelper, Zp1, Zp2, 1.0e-10, &ierr));
}

double __cdecl DMSinv::finteHelper(double z)
{
    return _current->finte(z);
}

これは良い解決策IMOではありませんが、他の方法があるかどうかはわかりません。

PS 1つのスレッドの制限を削除するには、TLSスロットを使用するか、VC ++では__declspec(thread)だけを使用できます。後者の場合は、次のよう に追加__declspec(thread)します。しかし!!!スレッドごとの変数の数はプロセスに対して制限されていることに注意してください。詳しくはMSDNをご覧ください。_currentstatic __declspec(thread) DMSinv* _current;

アップデート

Disclamer:楽しみのためだけに。

理論的には、他の機会があります。オブジェクトにアタッチされた配列にアセンブリコードを格納できます。このアセンブリコードは、eipレジスタに基づいて__cdeclを__thiscallに単純に変換する__cdecl関数である必要があります。しかし、これは決して行われるべきではありません...:D

于 2013-03-27T12:22:19.423 に答える