- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi! I have interoperable Fortran code that C can call ODRPACK95. At least it works without passing optional argument from C. And now is it possbile way to pass optional argument from C?
Fortran code:
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),value :: N,M,NP,NQ real(c_double) :: BETA(1:NP),Y(1:N,1:NQ),X(1:N,1:M) !!!!!Optional variable !!!!!!!!Unfinished ! !integer(c_int), optional :: IFIXB(:),IFIXX(:,:),JOB,NDIGIT,MAXIT& !,IPRINT,LUNERR,LUNRPT,INFO ! !real(c_double), optional :: WE(:,:,:),WD(:,:,:),& ! TAUFAC,SSTOL,PARTOL,STPB(:),STPD(:,:),& ! SCLB(:),SCLD(:,:),LOWER(:),UPPER(:) ! ! integer(c_int), optional,pointer :: IWORK(:) !real(c_double), optional, pointer :: DELTA(:,:),WORK(:) !!!!!Call ODR call 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) end subroutine wrapper_ODR
wrapper_ODR in C code:
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);
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Why not make two wrapper subroutines?
wrapper_ODR as you have it above
wraqpper_ODR_short as you want for apparent initialization
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jimdempseyatthecove wrote:
Why not make two wrapper subroutines?
wrapper_ODR as you have it above
wraqpper_ODR_short as you want for apparent initializationJim Dempsey
I see! Maybe I can try it! Well, if I want to pass UPPER and LOWER from C to Fortran, what does it look like?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I believe ifort officially supports using BIND(C) with optional arguments. I have small working example based on this post, http://stackoverflow.com/questions/40089567/calling-fortran-subroutines-with-optional-arguments-from-c
Optional arguments that are not PRESENT cannot be referenced. The call to ODR references optional arguments (e.g. WORK, IWORK) that may not be present which would cause a run-time fault.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Although I might be wrong, https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/393207#comment-1737916. I'm checking w/Development.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
When using BIND(C) with OPTIONAL and compiling with /stand:f08 the compiler issues a warning:
sub.f90(1): warning #8809: An OPTIONAL or EXTERNAL dummy argument to a BIND(C) procedure is not interoperable.
subroutine fort_foo(i, x) bind(C, name="fort_foo")
In the Fortran 2008 standard it is not legal to have an OPTIONAL argument with a BIND(C).
The 17.0 release includes support for some Fortran 2015 features from the "Technical Specification 29113 Further Interoperability with C", so it works in this version.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Davis, Kevin D wrote:
I believe ifort officially supports using BIND(C) with optional arguments. I have small working example based on this post, http://stackoverflow.com/questions/40089567/calling-fortran-subroutines-with-optional-arguments-from-c
Optional arguments that are not PRESENT cannot be referenced. The call to ODR references optional arguments (e.g. WORK, IWORK) that may not be present which would cause a run-time fault.
Yes! I believe BIND(C) still works with OPTIONAL arguments, The example can run in my environment. For example
!!!!!Optional variable integer(c_int), intent(in), optional :: IFIXB(:),IFIXX(:,:),JOB,NDIGIT,MAXIT& ,IPRINT,LUNERR,LUNRPT,IWORK(:),INFO real(c_double), intent(in), optional :: DELTA(:,:),& WE(:,:,:),WD(:,:,:),TAUFAC,SSTOL,PARTOL,& STPB(:),STPD(:,:),SCLB(:),SCLD(:,:),& WORK(:),LOWER(:),UPPER(1:NP) !!!!!Call ODR if(present(UPPER)) then call ODR(FCN=FCN,N=N,M=M,NP=NP,NQ=NQ,BETA=BETA,Y=Y,X=X,UPPER=UPPER) end if
Above code can be used when I need to use UPPER argument, however sometimes I use UPPER and LOWER or only using LOWER, so call ODR(...) and if(present(...)) statements keep adjusting all the time. Well that is a little inconvinent.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm may be misreading your post and perhaps you already have this; however, you can create an IF/ELSEIF construct to cover each unique case having different optional arguments present to call OCR accordingly rather than regularly adjusting the source for when only certain arguments are present/used.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Why not make the scalar arguments call by reference? Then pass a null pointer from the C side for missing arguments.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If UPPER and LOWER were optional dummy arguments inside ODR, then you may simply pass the corresponding actual argument along, even if it is not present.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I didn't realize you could pass along optional arguments downstream, so I gave it a try, but ran into some trouble and got some unexpected behavior. I attached an example to highlight what I am seeing. I am using Linux version 17.0.0.
If I compile using debug flags, then the compiler has trouble knowing that an optional dummy argument is missing. If I put the interface in the main file, or if I call the subroutine from a contains in the main file, it works. It also works with no flags, but I haven't tested with any other flags. I'm not sure if it helps, but if I use an older compiler (e.g. v12), I see the same wrong behavior, but it is independent of any compiler flags.
It looks like a bug to me.
Here is how I am compiling:
#!/bin/bash # this works with v17 flags="" ifort ${flags} -o test_optional test_optional.f90 test_optional_sub.f90 echo "Running with no debug flags" ./test_optional echo "" # this does not flags="-O0 -sox -traceback -debug extended -g" ifort ${flags} -o test_optional test_optional.f90 test_optional_sub.f90 echo "Running with debug flags" ./test_optional echo ""
Here is my output:
Running with no debug flags test passing of optional arguments calling s1 directly hi, subroutine s1 three = 3.000000 calling s2, then s1 indirectly hi, subroutine s2 calling s1 hi, subroutine s1 three = 3.000000 calling s3 (program contains), then s1 indirectly hi, subroutine s3 calling s1 hi, subroutine s1 three = 3.000000 Running with debug flags test passing of optional arguments calling s1 directly hi, subroutine s1 three = 3.000000 four = 3.000000 -- this should not be printed calling s2, then s1 indirectly hi, subroutine s2 calling s1 hi, subroutine s1 three = 3.000000 four = 3.000000 -- this should not be printed calling s3 (program contains), then s1 indirectly hi, subroutine s3 calling s1 hi, subroutine s1 three = 3.000000
Main program:
program test implicit none real one, two, three ! uncomment to make call to s2 work, when debugging symbols added ! interface ! subroutine s1(one, two, three, four) ! implicit none ! real, intent(in) :: one, two ! real, intent(in), optional :: three, four ! end subroutine s1 ! end interface one = 1. two = 2. three = 3. write(*,*) 'test passing of optional arguments' write(*,*) 'calling s1 directly' call s1(one, two, three) write(*,*) 'calling s2, then s1 indirectly' call s2(one, two, three) write(*,*) 'calling s3 (program contains), then s1 indirectly' call s3(one, two, three) contains subroutine s3(one, two, three, four) implicit none real, intent(in) :: one, two real, intent(in), optional :: three, four write(*,*) ' hi, subroutine s3 calling s1' call s1(one, two, three, four) end subroutine s3 end program test
Subroutines:
subroutine s1(one, two, three, four) implicit none real, intent(in) :: one, two real, intent(in), optional :: three, four write(*,*) ' hi, subroutine s1' if (present(three)) then write(*,*) ' three = ', three end if if (present(four)) then write(*,*) ' four = ', four, "-- this should not be printed" end if end subroutine s1 subroutine s2(one, two, three, four) implicit none real, intent(in) :: one, two real, intent(in), optional :: three, four interface subroutine s1(one, two, three, four) implicit none real, intent(in) :: one, two real, intent(in), optional :: three, four end subroutine s1 end interface write(*,*) ' hi, subroutine s2 calling s1' call s1(one, two, three, four) end subroutine s2
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page