我正在尝试将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的中间函数。
我在论坛中搜索过并发现了这个相关的问题: 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 :(得分:0)
我认为你不能这样做。您需要以某种方式将引用传递给您的对象(this
)。在链接的问题中,函数的参数被定义为类型void *
,因此您可以将所需的任何内容传递给函数,包括指向this
的指针。您的函数接受double
,因此您无法将this
传递给它。
我认为最简单的方法是在课外定义你的中间函数,因为它似乎独立于类内部。像这样:
double finte(double z)
{
return TFStolz(z, Zcglob);
}
您还可以将实例指针存储在静态函数可以读取的公共全局/静态类内变量中。
答案 1 :(得分: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 强>
要删除一个线程的限制,您可以使用TLS插槽或仅使用VC ++ __declspec(thread)。
后者只需将__declspec(thread)
添加到_current
,就像这样:static __declspec(thread) DMSinv* _current;
。但!!!请注意,每个线程变量的数量对于进程是有限的。在MSDN中阅读更多相关内容。
<强>更新强>
Disclamer:只是为了好玩。
理论上,还有其他机会。您可以将汇编代码存储在附加到对象的数组中。这个汇编代码应该是一个__cdecl函数,它只是根据eip寄存器将__cdecl转换为__thiscall。但是,这应该永远不会完成......:D