Re: Calling C++ from Fortran
- From: Catherine Rees Lay <spamtrap@xxxxxxxxxxxxxx>
- Date: Thu, 05 Jan 2006 14:30:29 +0000
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. .
- References:
- Calling C++ from Fortran
- From: Scott C
- Re: Calling C++ from Fortran
- From: Jugoslav Dujic
- Calling C++ from Fortran
- Prev by Date: Re: Kind of NOT integer constant
- Next by Date: Re: Reading data from file question.
- Previous by thread: Re: Calling C++ from Fortran
- Next by thread: Re: Calling C++ from Fortran
- Index(es):
Relevant Pages
|