Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29251 Обсуждение

Passing strings to C++ from ifort 12

Dimitrios_T_
Начинающий
1 244Просмотр.

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 баллов
7 Ответы
mecej4
Почетный участник III
1 244Просмотр.

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.

Simon_Geard
Новый участник I
1 244Просмотр.

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]

Dimitrios_T_
Начинающий
1 244Просмотр.

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 

jimdempseyatthecove
Почетный участник III
1 244Просмотр.

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

Dimitrios_T_
Начинающий
1 244Просмотр.

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

jimdempseyatthecove
Почетный участник III
1 244Просмотр.

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

Dimitrios_T_
Начинающий
1 244Просмотр.

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.

Ответить