|
|||
|
Hi, everyone.
I have a simple question about this subject. I'm writing my first programs using interoperability and I'm facing the following situation: In the fortran program which calls the C++ functions I have the interface block interface real(c_double) function cfunc(x) bind(c) use iso_c_binding real(c_double) :: x end function cfunc subroutine cfunc2(x,y) bind(c) use iso_c_binding real(c_double) :: x, y end subroutine end interface (function cfunc2 has void type). The thing is that x isn't ever passed to the C++ functions unless I declare real(c_double), value :: x however, changing this in the interface to cfunc is enough to make it work for both functions, i.e., x will be correctly passed to cfunc2 as well. In the C++ source code, in addition to the functions themselves, I have the block extern "C" { double cfunc(double x); void cfunc2(double x, double y); } which must be present, otherwise I'll get 'undefined references' at the time of linking. Is this somehow related to the expected behaviour of interfaces / interface blocks, or is it more an inreop. thing? Thanks in advance, Seneika. PS: I don't know whether it's relevant or not, but I'm using only GNU tools (MinGW). |
|
|
||||
|
||||
|
|
|
|||
|
I'm sorry, it was just gargage. It occurred consistently
after 3 or 4 project rebuilds but it didn't happen again since. So things will only work correctly if the 'pass by value' is declared in every function interface. Thanks anyway. Seneika. |
|
|||
|
On 2012-05-09 6:14 AM, Seneika wrote:
> Hi, everyone. > > I have a simple question about this subject. > > I'm writing my first programs using interoperability and I'm > facing the following situation: In the fortran program which > calls the C++ functions I have the interface block > > > interface > > real(c_double) function cfunc(x) bind(c) > use iso_c_binding > real(c_double) :: x > end function cfunc > > subroutine cfunc2(x,y) bind(c) > use iso_c_binding > real(c_double) :: x, y > end subroutine > > end interface > > > (function cfunc2 has void type). The thing is that x isn't ever > passed to the C++ functions unless I declare > > real(c_double), value :: x > > however, changing this in the interface to cfunc is enough to > make it work for both functions, i.e., x will be correctly passed > to cfunc2 as well. > > In the C++ source code, in addition to the functions themselves, > I have the block > > extern "C" > { > double cfunc(double x); > void cfunc2(double x, double y); > } Both functions here are taking all their arguments by value (which is the norm in C). Consequently all arguments in the interface blocks in the Fortran must be declared to have the VALUE attribute. (From what you write above, it reads as if you are saying that the declaration of an argument in one procedure definition in the Fortran code is somehow bleeding through to another. If that were the case it would be a compiler bug - each procedure definition in each interface block has its own scope. Note your code as presented may not be a sufficient test that a bug like this actually exists - but just in case - what specific version of gfortran are you using (4.???.???).) Style ramblings: Because each procedure has its own scope it also has its own set of implicit typing rules - in the absence of a specification to the contrary this is the ye-olde Fortran default of I-M INTEGER, others REAL. While procedure declarations are small and hence simpler to scan and check, a mistyped argument name could still occur - so consider adding IMPLICIT NONE. Consider also adding argument INTENT's - for a code documentation benefit at least, let alone the additional opportunities for the compiler to detect program logic errors, etc. Future standard revisions could place lots of additional things in ISO_C_BINDING. If one of those future symbols clashes with a name in the scope of the USE statement, then your code will no longer be valid against those future standards. To future proof against such a change consider adding the ONLY clause to the use statement to only pull in the things that you really need from that module. > which must be present, otherwise I'll get 'undefined references' > at the time of linking. C++ needs to distinguish at link time between functions with the same name in source that take parameters (to use the C term) of different type (differentiate between "overloads"). It does this by "mangling" (or perhaps "decorating", depending on your taste in names) the linker name with a compiler specific encoding of the parameter types. Adding extern "C" turns this off - the linker name for the function will then be equivalent to what a C compiler would produce for that function (this is really the nub of the idea of extern "C"). A consequence of this is that you cannot then overload extern "C" functions in C++. In Fortran, you can also "overload" procedures through the use of generics - where one generic may have several specific procedures that can be distinguished on the type, kind and rank of their arguments. In this case the mangling of the name of the specific is managed by the programmer. INTERFACE DoMagic PROCEDURE DoMagic_for_integer PROCEDURE DoMagic_for_real PROCEDURE DoMagic_for_character END INTERFACE DoMagic > Is this somehow related to the expected behaviour of interfaces / > interface blocks, or is it more an inreop. thing? > > Thanks in advance, > Seneika. > > PS: I don't know whether it's relevant or not, but I'm using only > GNU tools (MinGW). |
|
|||
|
Seneika <not.spam.me@today.com> wrote:
> I'm writing my first programs using interoperability and I'm > facing the following situation: In the fortran program which > calls the C++ functions I have the interface block Well, C interoperability only works with C functions, or with extern "C" in C++, which makes them C functions. > interface > real(c_double) function cfunc(x) bind(c) > use iso_c_binding > real(c_double) :: x > end function cfunc Remember that C uses call by value, and Fortran doesn't unless you put the VALUE attribute on. Without VALUE, you get a pointer (to the appropriate type) in the C function. > subroutine cfunc2(x,y) bind(c) > use iso_c_binding > real(c_double) :: x, y > end subroutine > end interface > (function cfunc2 has void type). The thing is that x isn't ever > passed to the C++ functions unless I declare > real(c_double), value :: x Well, yes, x isn't passed but a pointer to it is. That won't look much like x, so you might think it isn't passed. > however, changing this in the interface to cfunc is enough to > make it work for both functions, i.e., x will be correctly passed > to cfunc2 as well. No, you need VALUE in each function/subroutine. (snip) > extern "C" > { > double cfunc(double x); > void cfunc2(double x, double y); > } > which must be present, otherwise I'll get 'undefined references' > at the time of linking. Yes, otherwise they are C++ functions. I usually put the whole function inside extern "C", but maybe it works this way. > Is this somehow related to the expected behaviour of interfaces / > interface blocks, or is it more an inreop. thing? It is the expected behavior of call by value C functions. -- glen |
|
|||
|
glen herrmannsfeldt <gah@ugcs.caltech.edu> wrote:
> Seneika <not.spam.me@today.com> wrote: > > > I'm writing my first programs using interoperability and I'm > > facing the following situation: In the fortran program which > > calls the C++ functions I have the interface block > > Well, C interoperability only works with C functions, > or with extern "C" in C++, which makes them C functions. Well, strictly speaking, per the first sentence of Section 15 in f2003, C interop works with "procedures that are defined by means of the C programming language or procedures that can be described by C prototypes...". The extern "C" puts them in that second group. I'm not enough of a C++ expert (as in I'm not even up top novice level) to know the fine details, but I rather doubt that the extern "C" actually makes them C functions. I'd expect it more to make them interoperable with C functions in a similar sense to the way that Fortran procedures can be. -- Richard Maine | Good judgment comes from experience; email: last name at domain . net | experience comes from bad judgment. domain: summertriangle | -- Mark Twain |
|
|||
|
Richard Maine <nospam@see.signature> wrote:
(snip, I wrote) >> Well, C interoperability only works with C functions, >> or with extern "C" in C++, which makes them C functions. > Well, strictly speaking, per the first sentence of Section 15 in f2003, > C interop works with "procedures that are defined by means of the C > programming language or procedures that can be described by C > prototypes...". > The extern "C" puts them in that second group. Sounds reasonable to me. In any case, there is no C++ interoperabilty, to directly call C++ routines from Fortran. > I'm not enough of a C++ expert (as in I'm not even up > top novice level) to know the fine details, but I rather > doubt that the extern "C" actually makes them C functions. Yes, I don't know what they are supposed to be called, either. I sometimes claim to be able to debug C++, but usually don't claim to write it. I would call extern "C" C++'s C-interoperability, but I don't know if that is close to what it is supposed to be, or not. > I'd expect it more to make them interoperable with C > functions in a similar sense to the way that Fortran > procedures can be. -- glen |
|
|||
|
On 05/09/2012 05:50 PM, Tim Prince wrote:
> More to the point, I sometimes see reference parameters used with > iso_c_binding and extern "C". I don't know whether this depends on > specific implementations of C++ and Fortran or whether it may be implied > by the fact that the Fortran default is not to use value. > Evidently, a C++ function which is called through iso_c_binding may use > all sorts of C++ stuff, not limited to STL, which wouldn't work if that > "makes them C functions." I also very much doubt that C++ stack-unwinding (when an exception is thrown) can traverse a Fortran function, so I wouldn't feel comfortable mixing Fortran and C++ code. Regards, Thomas |
|
|||
|
On 05/08/2012 06:16 PM, glen herrmannsfeldt wrote:
> Richard Maine<nospam@see.signature> wrote: > > (snip, I wrote) >>> Well, C interoperability only works with C functions, >>> or with extern "C" in C++, which makes them C functions. > >> Well, strictly speaking, per the first sentence of Section 15 in f2003, >> C interop works with "procedures that are defined by means of the C >> programming language or procedures that can be described by C >> prototypes...". > >> The extern "C" puts them in that second group. > > Sounds reasonable to me. > > In any case, there is no C++ interoperabilty, to directly call > C++ routines from Fortran. > >> I'm not enough of a C++ expert (as in I'm not even up >> top novice level) to know the fine details, but I rather >> doubt that the extern "C" actually makes them C functions. > > Yes, I don't know what they are supposed to be called, either. > I sometimes claim to be able to debug C++, but usually don't > claim to write it. > > I would call extern "C" C++'s C-interoperability, but I don't > know if that is close to what it is supposed to be, or not. > >> I'd expect it more to make them interoperable with C >> functions in a similar sense to the way that Fortran >> procedures can be. > > -- glen More to the point, I sometimes see reference parameters used with iso_c_binding and extern "C". I don't know whether this depends on specific implementations of C++ and Fortran or whether it may be implied by the fact that the Fortran default is not to use value. Evidently, a C++ function which is called through iso_c_binding may use all sorts of C++ stuff, not limited to STL, which wouldn't work if that "makes them C functions." |
|
|||
|
Thomas Jahns <jahns@idontlikespam.dkrz.de> wrote:
> On 05/09/2012 05:50 PM, Tim Prince wrote: > > More to the point, I sometimes see reference parameters used with > > iso_c_binding and extern "C". I don't know whether this depends on > > specific implementations of C++ and Fortran or whether it may be implied > > by the fact that the Fortran default is not to use value. > > Evidently, a C++ function which is called through iso_c_binding may use > > all sorts of C++ stuff, not limited to STL, which wouldn't work if that > > "makes them C functions." > > I also very much doubt that C++ stack-unwinding (when an exception is thrown) > can traverse a Fortran function, so I wouldn't feel comfortable mixing Fortran > and C++ code. That's well past my level of C++, but if the stack unwinding relates to the C setjmp/longjmp, the Fortran standard has explicit prohibitions related to those in interop. -- Richard Maine | Good judgment comes from experience; email: last name at domain . net | experience comes from bad judgment. domain: summertriangle | -- Mark Twain |
|
|||
|
On 5/9/12 12:13 PM, Richard Maine wrote:
> Thomas Jahns<jahns@idontlikespam.dkrz.de> wrote: > >> On 05/09/2012 05:50 PM, Tim Prince wrote: >>> More to the point, I sometimes see reference parameters used with >>> iso_c_binding and extern "C". I don't know whether this depends on >>> specific implementations of C++ and Fortran or whether it may be implied >>> by the fact that the Fortran default is not to use value. >>> Evidently, a C++ function which is called through iso_c_binding may use >>> all sorts of C++ stuff, not limited to STL, which wouldn't work if that >>> "makes them C functions." >> >> I also very much doubt that C++ stack-unwinding (when an exception is thrown) >> can traverse a Fortran function, so I wouldn't feel comfortable mixing Fortran >> and C++ code. > > That's well past my level of C++, but if the stack unwinding relates to > the C setjmp/longjmp, the Fortran standard has explicit prohibitions > related to those in interop. > There is also a restriction against exception handling and a requirement that a non-Fortran routine returns to its caller (unless it terminates). Dick Hendrickson |
|
|||
|
Dick Hendrickson <dick.hendrickson@att.net> wrote:
> On 5/9/12 12:13 PM, Richard Maine wrote: > > Thomas Jahns<jahns@idontlikespam.dkrz.de> wrote: > > > > That's well past my level of C++, but if the stack unwinding relates to > > the C setjmp/longjmp, the Fortran standard has explicit prohibitions > > related to those in interop. > > > There is also a restriction against exception handling and a requirement > that a non-Fortran routine returns to its caller (unless it terminates). Hmm. I can't find the one about needing to return to its caller, at least not phrased in that way. Are you just deducing that as a consequence of the setjmp/longjmp restriction or is there some separate restriction that I missed? I looked around f2008 a little, thinking it might be something there, but I didn't find it there either. Perhaps somewhere in the co-array stuff about images, which I don't know my way around? And I do see restrictions relating to exception handling, but the ones I see are somewhat limitted. You can't have a Fortran procedure as a handler, and you can't muck with exceptions that the Fortran processor uses (that last one possibly being pretty broad, I suppose). (Of course, make my informal "you can't" into a variant of "shall not" for proper standard-speak.) -- Richard Maine | Good judgment comes from experience; email: last name at domain . net | experience comes from bad judgment. domain: summertriangle | -- Mark Twain |
|
|||
|
On 5/9/12 3:33 PM, Richard Maine wrote:
> Dick Hendrickson<dick.hendrickson@att.net> wrote: > >> On 5/9/12 12:13 PM, Richard Maine wrote: >>> Thomas Jahns<jahns@idontlikespam.dkrz.de> wrote: >>> >>> That's well past my level of C++, but if the stack unwinding relates to >>> the C setjmp/longjmp, the Fortran standard has explicit prohibitions >>> related to those in interop. >>> >> There is also a restriction against exception handling and a requirement >> that a non-Fortran routine returns to its caller (unless it terminates). > > Hmm. I can't find the one about needing to return to its caller, at > least not phrased in that way. Are you just deducing that as a > consequence of the setjmp/longjmp restriction or is there some separate > restriction that I missed? I looked around f2008 a little, thinking it > might be something there, but I didn't find it there either. Perhaps > somewhere in the co-array stuff about images, which I don't know my way > around? > > And I do see restrictions relating to exception handling, but the ones I > see are somewhat limitted. You can't have a Fortran procedure as a > handler, and you can't muck with exceptions that the Fortran processor > uses (that last one possibly being pretty broad, I suppose). (Of course, > make my informal "you can't" into a variant of "shall not" for proper > standard-speak.) > I was looking at Note 12.45 and lines 24ff on page 436 for setjmp stuff. The return to caller is the second paragraph of 12.6.3. Some of that is in notes (especially the note 12.45 stuff ) or text. But, I'dguess the intent is clear(?) that other languages can't mess with the call/return sequence. This is all F2008. Dick Hendrickson |
|
|||
|
Dick Hendrickson <dick.hendrickson@att.net> wrote:
> On 5/9/12 3:33 PM, Richard Maine wrote: > > Dick Hendrickson<dick.hendrickson@att.net> wrote: > >> There is also a restriction against exception handling and a requirement > >> that a non-Fortran routine returns to its caller (unless it terminates). > > > > Hmm. I can't find the one about needing to return to its caller, at > > least not phrased in that way. > I was looking at Note 12.45 and lines 24ff on page 436 for setjmp stuff. > The return to caller is the second paragraph of 12.6.3. Some of that > is in notes (especially the note 12.45 stuff ) or text. But, I'd> guess the intent is clear(?) that other languages can't mess with the > call/return sequence. This is all F2008. Ah. Thanks. I figured you probably weren't just making that up, even though the general idea pretty much does follow from material I did find. I was looking in the C interop Section, with a skim way up front where it talks about execution sequence. I didn't think to look in C12. Looks like it is broader than just C interop and applies to any procedure "defined by means other than Fortran." Makes sense. That restriction is new to f2008, at least in quite those terms. But it looks to me like it amounts to broadening the material of f2003 so that it gets to the important issue from the Fortran perspective instead of the niggly details of specific C features that looked problematic to someone. I'd say it was an improvement (and probably makes the restriction about setjmp/longjmp redundant; the note 12.45 even mentions setjmp/longjump as an example). -- Richard Maine | Good judgment comes from experience; email: last name at domain . net | experience comes from bad judgment. domain: summertriangle | -- Mark Twain |
|
|||
|
On 05/09/2012 03:59 PM, Thomas Jahns wrote:
> On 05/09/2012 05:50 PM, Tim Prince wrote: >> More to the point, I sometimes see reference parameters used with >> iso_c_binding and extern "C". I don't know whether this depends on >> specific implementations of C++ and Fortran or whether it may be implied >> by the fact that the Fortran default is not to use value. >> Evidently, a C++ function which is called through iso_c_binding may use >> all sorts of C++ stuff, not limited to STL, which wouldn't work if that >> "makes them C functions." > > I also very much doubt that C++ stack-unwinding (when an exception is thrown) > can traverse a Fortran function, so I wouldn't feel comfortable mixing Fortran > and C++ code. > > Regards, Thomas From experience, I can tell that mixing Fortran and C++ works excellently, if the C interop conventions and extern "C" are consistently used. I try to avoid messing with some of the more nasty C++ stuff (exceptions), but I had a project which mixed Fortran and Qt, including the signal-slot stuff, which did work. Caveat: This is on Unix-like OS. I always had the impression that the idea of BIND(C) is not to interoperate with C programs as such, but rather to implement calling conventions that are compatible with standard OS conventions where possible, and nowadays the OS is often written in C. If I want to write a portable library in Fortran, I'd try to make all externally visible procedures BIND(C). Then, programs written in any language with a C-compatible interface can use it. -- Wolfgang -- E-mail: firstnameinitial.lastname@domain.de Domain: yahoo |
|
|||
|
On 2012-05-10 4:44 PM, Wolfgang Kilian wrote:
.... > Caveat: This is on Unix-like OS. I always had the impression that the > idea of BIND(C) is not to interoperate with C programs as such, but > rather to implement calling conventions that are compatible with > standard OS conventions where possible, and nowadays the OS is often > written in C. BIND(C) matches the companion C compiler. Your impression is a symptom of practical implementation (amplified by your nominated subset of OS's), not the fundamental intent. Practical implementations of C compilers commonly use calling conventions that match their host OS (or the system compiler of the host OS) - hence implementations of BIND(C) in Fortran processors commonly use calling conventions that match their host OS. If you think otherwise then there's a rather significant and current example, where an OS that is still written predominantly in C does not have a typical "C like" calling convention, hence BIND(C) usually nominates something very contrary to the OS convention. There are also (perhaps rather esoteric) examples where a particular OS has multiple Fortran processors available, those processors have different notional companion C compilers, and those C compilers differ in their calling conventions. > If I want to write a portable library in Fortran, I'd try > to make all externally visible procedures BIND(C). Then, programs > written in any language with a C-compatible interface can use it. That's reasonable to an extent - BIND(C) interfaces mean that you lose many of the nicer features of the language. The cost of that would need to be weighed against the benefit of providing access to clients using different languages. Providing two variants of the interface - a basic BIND(C) interface and a richer Fortran interface - may also be worthwhile, but again that comes with a cost. > > -- Wolfgang > |
|
|
![]() |
| Thread Tools | |
| Display Modes | |
|
|