2013-03-27 78 views
0

我试图加入一个旧的代码在C我现在的VC++项目:错误C2664和MyClass的冲突

// .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的中间函数。

我搜索的论坛,发现此相关的问题: How to convert void (__thiscall MyClass::*)(void *) to void (__cdecl *)(void *) pointer ,我试图以这种方式适用于:

// .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; 
    } 

,但仍然没有工作。有人可以指导我如何适应它吗?我还是一个新手,这似乎离我的知识还很遥远。

在此先感谢!

+0

'DMSinv * datainv = reinterpret_cast < DMSinv >(z)' - 不应该转换为'DMSinv *'吗? – SomeWittyUsername 2013-03-27 11:56:10

+0

我试过了,但是这给了我同样的错误:'错误C2440:'reinterpret_cast':无法从'double'转换为'DMSinv *'' – madoro 2013-03-27 11:58:14

回答

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); 
} 

这不是很好的解决方案海事组织,但我不知道有其他的方式。

PS 要删除限制一个线程,你可以使用TLS插槽或VC++只是__declspec(thread)。 后者只需将__declspec(thread)加到_current就可以这样:static __declspec(thread) DMSinv* _current;。但!!!注意每个线程变量的数量对于进程是有限的。在MSDN上阅读更多信息。

UPDATE

Disclamer:只是为了好玩。

理论上还有其他的机会。您可以将汇编代码存储在数组中,并附加到对象上。这个汇编代码应该是一个__cdecl函数,它简单地将__cdecl转换为基于eip寄存器的__thiscall。但是这不应该通过...来实现:D

+0

为什么它要求我在finiteHelper中返回一个值,在静态时它是否需要? '错误C4716:'DMSinv :: finteHelper':必须返回一个值'。感谢'__declspec(thread)',看起来很有趣,我会看看。 – madoro 2013-03-27 12:56:08

+0

我已更新我的代码以修复此错误。只需添加return,编译器问你。 – 2013-03-27 12:59:13

+0

好的,谢谢,现在它编译,但没有运行,在某些时候打破。我会继续研究为什么会发生这种情况,正如你所说这可能不是最佳解决方案,但感谢您的帮助! – madoro 2013-03-27 13:08:03

0

我不认为你可以这样做。你需要以某种方式将引用传递给你的对象(this)。在链接问题中,该函数的参数定义为void *,因此您可以将所需的任何内容传递给该函数,包括指向this的指针。你的功能接受double,所以你不能通过this它。

我认为最简单的方法就是在课堂外定义中间函数,因为它看起来独立于类内部。类似这样的:

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

您还可以将实例指针存储在静态函数可以读取的公共全局/静态in-class变量中。

+0

这似乎是一个简单而干净的解决方案,但TFStolz是一个函数类DMSinv,所以如果当finte超出课堂时,它不会识别TFStolz:错误C3861:'TFStolz':标识符未找到。也许有些时候,包括TFStolz在内的指针......我不得不重新考虑它,因为我说我是一个新手,不能轻松解决这个问题。谢谢! – madoro 2013-03-27 12:50:32