【发布时间】:2013-09-19 07:32:04
【问题描述】:
我一直在尝试通过使用 extern "C" 在 C++ 中声明 ARPACK 函数来查找矩阵的特征向量:
extern "C" {void znaupd_(int *IDO, char *BMAT, int *N, char *WHICH,
int *NEV, double *TOL, complex<double> *RESID,
int *NCV, complex<double> *V, int *LDV,
int *IPARAM, int *IPNTR, complex<double> *WORKD,
complex<double> *WORKL, int *LWORKL,
double *RWORK, int *INFO);}
extern "C" {void zneupd_(bool *RVEC, char *HOWMNY, bool *SELECT,
complex<double> *D, complex<double> *Z,
int *LDZ, complex<double> *WORKEV,
complex<double> *SIGMA, char *BMAT, int *N,
char *WHICH, int *NEV, double *TOL,
complex<double> *RESID, int *NCV,
complex<double> *V, int *LDV, int *IPARAM,
int *IPNTR, complex<double> *WORKD,
complex<double> *WORKL, int *LWORKL, int *INFO);}
然后,在我的代码主体中,我调用函数:
do{
znaupd_(&IDO, &BMAT, &N, WHICH, &NEV, &TOL, RESID, &NCV, V, &LDV, IPARAM,
IPNTR, WORKD, WORKL, &LWORKL, RWORK, &INFO);
switch(abs(IDO)){
case - 1:
for(i = 0; i < N; i++) X[i] = WORKD[IPNTR[1] + i];
gmm::mult(SM, X, Y);
for(i = 0; i < N; i++) WORKD[IPNTR[2] + i] = Y[i];
break;
case 1:
for(i = 0; i < N; i++) X[i] = WORKD[IPNTR[1] + i];
gmm::mult(SM, X, Y);
for(i = 0; i < N; i++)
{WORKD[IPNTR[2] + i] = Y[i];
WORKD[IPNTR[3] + i] = X[i];}
break;
case 2:
for(i = 0; i < N; i++)
WORKD[IPNTR[2] + i] = WORKD[IPNTR[1] + i];
break;
}
}while(IDO != 99);
std::cout << &INFO << std::endl;
zneupd_(&RVEC, &HOWMNY, SELECT, D, Z, &LDZ, WORKEV, &SIGMA, &BMAT, &N,
WHICH, &NEV, &TOL, RESID, &NCV, V, &LDV, IPARAM, IPNTR, WORKD,
WORKL, &LWORKL, &INFO);
然而,在编译和执行之后,程序会出现段错误。使用 GDB 执行回溯显示 &INFO 传递给 zneupd_ 的地址为 0x0,这会导致当 zneupd_ 尝试为该位置分配新值时出现段错误。然而,当我移动到下一帧并使用 print &INFO 时,我被告知 INFO 存储在寄存器 0x28a27c 中。出于某种原因,我的程序没有正确地将 INFO 的位置传递给 zneupd_。更令人困惑的是znaupd_能够正确接收&INFO,并且能够毫无问题地访问和修改该位置的值。谁能告诉我为什么一个函数可以正确接收参数,而另一个不能?
【问题讨论】:
-
对于某些编译器,您必须指定函数的导出签名。 (yolinux.com/TUTORIALS/LinuxTutorialMixingFortranAndC.html)
-
漂亮的缩进和大括号样式!
-
@user1233963,讽刺的是:-)
标签: c++ fortran fortran77 arpack