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

Passing strings to C++ from ifort 12

Dimitrios_T_
Beginner
1,226 Views

Hello,

In the following code snippet I notice that string lengths are passed to C++ differently:

[fortran]
type MyPro
character(len=256) :: path
end type 

subroutine Test
implicit none

type(MyPro):: Pro
character(len=256):: path 
integer::err

!these call directly C++ functions defined as
! void dbGet(const char *key, char *pValue, int *err, size_t key_len, size_t value_len)
!
call dbGet("Path", Pro%path, err) 
call dbGet("Path", path, err) 
end subroutine
[/fortran]

The problem is that on the C++ side value_len gets a 0 value from the first fortran call, but the correct value from the second call.
 I would appreciate an explanation for this,

Thanks 

0 Kudos
7 Replies
mecej4
Honored Contributor III
1,226 Views

We need more details about how you compile and which compiler versions you use, as well as actual source code to demonstrate the problem. Using the attached files and IFort/Icl 13.1.1.171, in the debugger I see 4 and 256 inside DBGET for key_len and value_len during both calls to DBGET.

0 Kudos
Simon_Geard
New Contributor I
1,226 Views

This looks like a calling mechanism problem since Fortran doesn't know anything about C++ - it just has a standard way to interface with C. Is your program 32 or 64 bit? As far as I know there is only one calling convention on 64-bit whereas there is a whole plethora of them in 32-bit. I believe the standard is now to have a 1:1 correspondence between Fortran and C argument lists - no more hidden arguments. So with the right calling convention (or in 64-bit) you should be able to do

[fortran]

call dbGet("Path", Pro%path, err, len("Path"), len(Pro%path))

[/fortran]

0 Kudos
Dimitrios_T_
Beginner
1,226 Views

I seem to be unable to post the full text of my update here, so I attach it as a text file.
Please download and read,

Thanks 

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,226 Views

In your case 2 (type embedded), the NULL char you observed after the string is likely accidental.

type MyPro 
character(len=256) :: path 
integer :: flag
end type

Initialize path as before, but set flag to -1.

Jim Dempsey

0 Kudos
Dimitrios_T_
Beginner
1,226 Views

Thanks Jim, I checked with various stack data around the fortran type and it was indeed accidental. This leaves the #2 issue still unsolved.

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,226 Views

I suggest that since your C++ side interface explicitly uses a size argument that you declare the C++ interface on the FORTRAN side with explicit size arguments as sgearg suggests.

Note, you can create a shell function in FORTRAN that is passed (key,value,err) which calls the C++ function with  (key,value,err, LEN(key), LEN(value)). Or use LENTRIM in place of LEN.

Jim Dempsey

0 Kudos
Dimitrios_T_
Beginner
1,226 Views

Thanks everyone, I finally found a workaround without extra size arguments.since the general issue is to pass any type, array or string. My interface code depends on a custom data mining tool that extracts types from fortran files and their dependent embedded types (if any) and generates binary-compatible C++ structures. It also creates appropriate metadata describing each type, members, descriptors, sizes, etc. These structs have exactly the same size as the fortran types, so I use the metadata to extract the size of anything, including strings. I know, this deviates from my original question, but the issue was more general.

0 Kudos
Reply