Re: Calling C++ from Fortran



Jugoslav Dujic wrote:
Scott C wrote:
| I posted the following message a few days ago on
| comp.lang.c++.moderated, and it was suggested I post to a Fortran
| group.
| | interface to subroutine PythagorasA [STDCALL, Alias:'_PythagorasA@12']
| (a,b,c)
| real*4 a [VALUE]
| real*4 b [VALUE]
| real*4 c [REFERENCE]
| end


Not that I'm a particular purist, but that square-bracket syntax originates
from Microsoft Fortran 5 (ca. 1986) and PowerStation (ca. 1993.). It was superseded by !DEC$ syntax with later DEC/Compaq/Intel compilers.


| The next step, for me, was to try passing an array to C++. Here is the
| C++ function signature:
| | extern "C" __declspec( dllexport )
| int FillRandom(float* buf, int len);
| | and the FORTRAN implementation (ignore the word wrap):
| | interface
| integer function FillRandom(arr, size)
| !DEC$ ATTRIBUTES C, ALIAS:'_FillRandom@8', REFERENCE::FillRandom
| INTEGER :: size
| REAL*4 :: arr(*)
| end function FillRandom
| end interface
| | In the fortran, this function is called as:
| | real*4, POINTER :: arr(:)


Why POINTER? I mean, it will work, but it's an unnecessary complication.
A mere static array (real:: arr(2)) will serve just fine. There's also
ALLOCATABLE attribute which has much better "garbage collection" than
POINTER -- you have to DEALLOCATE the pointer yourself.

| integer*4 count
| allocate(arr(0:1))
| count = FillRandom(arr, 2)   ! ==> Access Violation !

You declared FillRandom with REFERENCE attribute, which means that
argument SIZE is to be passed by reference. In C code, it is declared
by value (int len). There comes your crash -- C routine does not
access 2 elements, but &(2) elements, whatever it happens to be (but it's probably large).


The rules and precedence of !DEC$ATTRIBUTES are a tad, ehm, complicated. Here's the ranking, starting from lowest to highest:

0) Without specified attributes, CVF calling convention is STDCALL, all arguments are passed by reference, string arguments have an additional
length, passed by value, immediately succeeding the string address.
1) DEC$ATTRIBUTES C and STDCALL imply VALUE for *scalar* arguments (arrays are always passed by reference, and strings as above)
2) DEC$ATTRIBUTES REFERENCE for the routine implies that all arguments are passed by reference
3) DEC$ATTRIBUTES VALUE and REFERENCE for individual arguments override
other implicit attributes as above. In addition, REFERENCE for string arguments suppresses hidden length argument.



I strongly recommend you look at the CVF help on "Mixed Language Programming" - it's very detailed and I found it extremely helpful.


Catherine.
.



Relevant Pages

  • Re: some c# questions!! please send me the answer
    ... TryParse first to see if the string is a valid DateTime before doing ... In .NET 1.1 all you can do is Prase and catch any exceptions ... Boxing is creating a "reference" shell around a value object so that it ... each "int" and then adds those object wrappers to the ...
    (microsoft.public.dotnet.csharp.general)
  • Re: Calling C++ from Fortran
    ... and it was suggested I post to a Fortran ... POINTER -- you have to DEALLOCATE the pointer yourself. ... You declared FillRandom with REFERENCE attribute, ... length, passed by value, immediately succeeding the string address. ...
    (comp.lang.fortran)
  • Re: Problem in declaration
    ... The way subroutine in which this statement, INTEGER*4 JR*2, ... an array of size INT. ... It seems that I need to have a reference book on MS FORTRAN. ...
    (comp.lang.fortran)
  • Re: Hayes 1200 8 & 10 Dips
    ... Do you have any reference to the Int. ... String that works best?? ... Les ...
    (alt.security.alarms)
  • Re: Simple Input File Parsing Question
    ... I am pretty new to programming in Fortran, and I am looking for a good ... reference on doing some input parsing tasks. ... What is a good reference for learning to parse strings in fortran? ... Loop through the header lines (read, goto). ...
    (comp.lang.fortran)