在C中调用Fortran包

时间:2016-11-29 10:26:54

标签: visual-c++ fortran intel-fortran fortran-iso-c-binding

我引用About using Fortran function in C with iso_c_binding编写一个中间程序,以便可以在C中调用Odrpack95(http://www.netlib.org/odrpack/)。但是我遇到了一些问题,需要别人的帮助。

Fortran代码

 UIImage *filteredImage = [[UIImage alloc] initWithCGImage:cgimg];

C代码

(我在ODRPACK95中翻译并修改了subroutine wrapper_ODR(FCN,N,M,NP,NQ,BETA,Y,X,& DELTA,WE,WD,IFIXB,IFIXX,JOB,NDIGIT,TAUFAC,& SSTOL,PARTOL,MAXIT,IPRINT,LUNERR,LUNRPT,& STPB,STPD,SCLB,SCLD,WORK,IWORK,INFO,LOWER,UPPER) bind(C, name='wrapper_ODR') !DEC$ ATTRIBUTES DLLEXPORT :: wrapper_ODR use iso_c_binding use ODRPACK95 implicit none interface subroutine FCN(N,M,NP,NQ,LDN,LDM,LDNP,BETA,XPLUSD,IFIXB,IFIXX,LDIFX,& IDEVAL,F,FJACB,FJACD,ISTOP) bind(C) use, intrinsic :: iso_c_binding implicit none integer(c_int) :: IDEVAL,ISTOP,LDIFX,LDM,LDN,LDNP,M,N,NP,NQ real (c_double) :: BETA(1:NP),F(1:LDN,1:NQ),FJACB(1:LDN,1:LDNP,1:NQ), & FJACD(1:LDN,1:LDM,1:NQ),XPLUSD(1:LDN,1:M) integer(c_int) :: IFIXB(1:NP),IFIXX(1:LDIFX,1:M) end subroutine end interface integer(c_int) :: N,M,NP,NQ real(c_double) :: BETA(1:NP),Y(1:N,1:NQ),X(1:N,1:M) !!!!!Optional integer(c_int), optional :: IFIXB(:),IFIXX(:,:),JOB,NDIGIT,MAXIT& ,IPRINT,LUNERR,LUNRPT,IWORK(:),INFO real(c_double), optional :: DELTA(:,:),& WE(:,:,:),WD(:,:,:),TAUFAC,SSTOL,PARTOL,& STPB(:),STPD(:,:),SCLB(:),SCLD(:,:),& WORK(:),LOWER(:),UPPER(:) call ODR(inter_func,N,M,NP,NQ,BETA,Y,X) contains subroutine inter_func(N,M,NP,NQ,LDN,LDM,LDNP,BETA,XPLUSD,IFIXB,IFIXX,LDIFX,& IDEVAL,F,FJACB,FJACD,ISTOP) use REAL_PRECISION integer :: IDEVAL,ISTOP,LDIFX,LDM,LDN,LDNP,M,N,NP,NQ REAL (KIND=R8) :: BETA(1:NP),F(1:LDN,1:NQ),FJACB(1:LDN,1:LDNP,1:NQ), & FJACD(1:LDN,1:LDM,1:NQ),XPLUSD(1:LDN,1:M) INTEGER :: IFIXB(1:NP),IFIXX(1:LDIFX,1:M) integer(c_int) :: inter_IDEVAL,inter_ISTOP,inter_LDIFX,inter_LDM,& inter_LDN,inter_LDNP,inter_M,inter_N,inter_NP,inter_NQ real (c_double) :: inter_BETA(1:size(BETA)),inter_F(1:size(F,1),1:size(F,2)),& inter_FJACB(1:size(FJACB,1),1:size(FJACB,3),1:size(FJACB,3)),& inter_FJACD(1:size(FJACD,1),1:size(FJACD,2),1:size(FJACD,3)),inter_XPLUSD(1:size(XPLUSD,1),1:size(XPLUSD,2)) integer(c_int) :: inter_IFIXB(1:size(IFIXB)),inter_IFIXX(1:size(IFIXX,1),1:size(IFIXX,2)) inter_IDEVAL = IDEVAL inter_ISTOP = ISTOP inter_LDIFX = LDIFX inter_LDM = LDM inter_LDN = LDN inter_LDNP = LDNP inter_M = M inter_N = N inter_NP = NP inter_NQ = NQ !!!!REAL inter_BETA = BETA inter_F = F inter_FJACB = FJACB inter_FJACD = FJACD inter_XPLUSD = XPLUSD !!!!INTEGER[] inter_IFIXB = IFIXB inter_IFIXX = IFIXX end subroutine inter_func end subroutine wrapper_ODR

simple_example.f90

#include "stdafx.h" #include <iostream> #include <stdio.h> #include <math.h> using namespace std; extern "C" { void wrapper_ODR(void(*FCN)(int*, int*, int*, int*, int*, int*, int*, \ double [] ,double [1][4],int [], int [],int* ,\ int*, double [1][4],double [1][2][4],double [] ,int* ),\ int *N,int *M,int *NP,int *NQ,double BETA[],double Y[1][4],double X[1][4],\ double DELTA[1][4],double WE[],double WD[],int IFIXB[],int IFIXX[],\ int *JOB,int *NDIGIT,double *TAUFAC,double *SSTOL, double *PARTOL,\ int *MAXIT, int *IPRINT, int *LUNERR, int *LUNRPT,double STPB[],\ double STPD[], double SCLB[], double SCLD[], double WORK[], double IWORK[],\ int *INFO, double LOWER[], double UPPER[]); } void FCN(int *N, int *M, int *NP, int *NQ, int *LDN, int *LDM, int *LDNP,\ double BETA[], double XPLUSD[1][4], int IXIFB[], int IFIXX[],int *LDIFX,\ int *IDEVAL, double F[1][4], double FJACB[1][2][4], double FJACD[],int *ISTOP){ // BETA[NP], XPLUSD[M][LDN], IXIFB[NP], IFIXX[M][LDIFX], F[NQ][LDN], FJACB[NQ][LDNP][LDN], FJACD[NQ][LDM][LDN] *ISTOP =5; if (fmod(*IDEVAL,10.0)!=0) { for (int i = 0; i < *N; i++) { F[0][i] = BETA[0] * XPLUSD[0][i] + BETA[1]; } } } int main(){ //X[M][N] Y[NQ][N],BETA[NP] int NP = 2, N = 4, M = 1, NQ = 1; double BETA[] = { 2.0, 0.5 }; double X[1][4] = { 0.0, 1.0, 2.0, 3.0 }; double Y[1][4] = { 2.0, 5.0, 8.0, 11.0 }; wrapper_ODR(&FCN, &N, &M, &NP, &NQ, BETA, Y, X, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, \ NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL, NULL, NULL, NULL, NULL, NULL, \ NULL, NULL); system("pause"); return 0; } NP = 2N = 4M = 1NQ = 1LDN = 4LDM = 1,{{1} }

问题

  1. LDNP = 2用于在LDIFX = 4不等于0时停止回归过程。但是,当执行上面的C代码时,无论ISTOP是什么,它都会继续回归程序。 ISTOP似乎没有传递给ISTOP

  2. 在Fortran代码中,带有ISTOP的注释部分表示为传递数组数据部分。好吧,它没有响铃如何通过subroutine inter_func变量将数组数据从C传递到Fortran或Fortran到C.

  3. 更新

    我修改了上面的C和Fortran代码,结果如下所示: Result 在C代码中,我设置ISTOP = 5,但结果报告显示它为0。

    然后,如果ODRPACK程序成功,它应该是这样的: enter image description here 这里还有从!修改的Fortran代码,它与C代码相同:

    inter_

    似乎C函数simple_example.f90的变量值没有传递给wrapper_ODR,但我不知道我的问题在哪里?有人能帮助我吗?

0 个答案:

没有答案