Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29267 Discussions

Mixed language - return an arry of char from C to FORTRAN

oddstray
Beginner
488 Views

Hi,

I have a mixed-language workspace. My FORTRAN *.exe calls a routine in my C *.dll and passes in a string. The dll then changes the string and my intention is to have that change passed back to my FORTRAN. But it doesn't happen. Can anyone tell me what I'm missing? Thanks!

B

The FORTRAN looks like this:

SUBROUTINE myFortran
!DEC$ ATTRIBUTES DEFAULT :: myFortran

  use dflogm

    implicit none

    ! connect to C method:
    !   void run_client(char *servIP, unsigned short servPort, char dataString[255])
    INTERFACE
        SUBROUTINE run_client( servIP, servPort, dataString )
          !DEC$ ATTRIBUTES DLLIMPORT :: run_client
          !DEC$ ATTRIBUTES STDCALL  :: run_client
          !DEC$ ATTRIBUTES ALIAS: "_run_client" :: run_client
          character*255 :: servIP,dataString
          integer*2     :: servPort
          !DEC$ ATTRIBUTES REFERENCE :: servIP,dataString
        END SUBROUTINE run_client
    END INTERFACE

    ! variables for run_client
    character*255 ipOfServer
    character*255 stringToSend
    integer*2 portOfServer

    ipOfServer = "134.120.71.207"
    portOfServer = 82
    stringToSend = "I'm calling to C"

    CALL run_client( TRIM(ipOfServer)//CHAR(0), &
                     portOfServer, &
                     TRIM(stringToSend)//CHAR(0) )

    ! At this point, I would hope that 'stringToSend'
    !  contains the reply from C but in fact it still
    !  has my call from FORTRAN

END SUBROUTINE myFortran

And the C looks like this:

void run_client(char *servIP, unsigned short servPort, char dataString[255])
{

    // experiment ...
    strcpy( dataString, "C is replying" );

    return;
}
0 Kudos
2 Replies
anthonyrichards
New Contributor III
488 Views

Try this recent thread http://software.intel.com/en-us/forums//topic/58864
where passing strings between a C main and a Fortran DLLis dealt with, but the advice still applies when it's a C DLL and Fortran main (just swap 'import' for 'export' and vice versa). You need to specify 'extern "C" for your C++ function and export the function name from it. This is how the referenced example treats the C++ function:

extern "C" { __declspec(dllimport) void __stdcall YOURCFUNCTION(char *lpszstring, int &strlength, char *lpszstrtospace, int &strtospacelength); }

The above statement when compiled in C++ should create _YOURCFUNCTION @16 as the symbol in your DLL.
On the Fortran side, this is the ALIAS you must give your Fortran function. Note that C preserves case, so if you define YourCfunction on the C++ side, then the symbol generated will be YourCfunction@16, and this becomes your required ALIAS.

Note that my preference is to always pass/receive addresses (pointers) as arguments when passing between C and Fortran, andto always explicitly supply the string length(s). On the Fortran side, all arguments are therefore specified as by REFERENCE and the character strings are dimensioned to the passed integer lengths. Remember that C++ exports null-terminated C-strings (terminated with the Fortran CHAR(0) character) and expects similarly terminated strings to be returned. When returning/receiveing such strings, you must allow for the extra null character when specifying the longest string that the Fortran function can handle.

0 Kudos
oddstray
Beginner
488 Views
Yes!!! Thank you! Thank you! Thank you!
0 Kudos
Reply