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

Passing string from fortran 90 to cpp dll

shilosh
Beginner
737 Views

Hello,

I realy spent to much time on this issue and I desperately need help.

I'm actually using the Compaq Visual Fortran. I want to call a cpp dll and pass a string to a function.

This is my fortran routine:

program call_dll
implicit none
! Variables
real*4, pointer ::f(:)
real*4 ::a
CHARACTER*33 sFileName

INTERFACE
function read_ras_format(sFileName)
!dec$ attributes stdcall ,dllimport,alias:'_read_ras_format' :: read_ras_format
real*4, pointer::read_ras_format(:)
character*33 sFileName
!character :: strFileName
END function read_ras_format
END INTERFACE
! Body of simple_dll_test
sFileName = 'E:\\temp\\SHA00200604010046RF.ras' // CHAR(0)
f => read_ras_format(sFileName)
a=f(1)
end program

and this is my cpp code:

extern "C"
float * __stdcall read_ras_format(char *in_fileName, int fileName_length)
{

cout<<"in_fileName: "<<<" fileName_length: "<

}

This is what I get:

in_fileName: _$@ fileName_length: 69

_______________

I read a lot of forum post about this issue, and I tried almost everything.

What am I doing wrong?

0 Kudos
4 Replies
anthonyrichards
New Contributor III
737 Views
Where in your C code do you return a value for read_ras_format? I cannot see an assignment in the following:

extern "C"
float * __stdcall read_ras_format(char *in_fileName, int fileName_length)
{

cout<<"in_fileName: "<<<" fileName_length: "<

}

0 Kudos
shilosh
Beginner
737 Views


I do return a float value, I just didn't paste it in my post because the return value is not the issue.I tested thecpp function by calling it from a cpp code and it works well. The problem us passing the string from forrtran to cpp.

0 Kudos
Jugoslav_Dujic
Valued Contributor II
737 Views
Quoting - shilosh


I do return a float value, I just didn't paste it in my post because the return value is not the issue.I tested thecpp function by calling it from a cpp code and it works well. The problem us passing the string from forrtran to cpp.

Shilosh, I replied to your post in comp.lang.fortran yesterday. Here it is again, for everyone's convenience:

Like Arjen said, you cannot mix Fortran and C pointers like that (at least not arrays). The rest of your code looks OK (and would likely have worked indeed with a void or a plain vanilla function). It seems that something ugly happened on the stack here.

What you can do is to declare the C function as returning an integer of address size, then dereference that into an array using a cray (integer) pointer. (It's unportable, but the rest of your code isn't portable either, so it doesn't matter).

Along the lines of (my changes uppercase):

[cpp]REAL:: F(*); POINTER(pF,F) !An integer (Cray) pointer

interface
  function read_ras_format(sFileName)
  !dec$ attributes  stdcall ,dllimport,alias:'_read_ras_format' ::
read_ras_format
  INTEGER(INT_PTR_KIND())::read_ras_format
...

pF = read_ras_format(sFileName)
!et voila:
DO i=1,SOMETHING
   WRITE(*,*) F(i)
END DO
[/cpp]

====
where SOMETHING is the array size -- I assume you know it by some means, because i don't see it referenced anyway in your original code.

0 Kudos
anthonyrichards
New Contributor III
737 Views
Are you trying to return a pointer to the filename?
I removed stdcall and changed the function to 'int'. The following works when both C++ DLL and Fortran main console programare linked to the same single threaded DLL libraries (so that the cout output in the C++ can appear in the console window). You have to add the .LIB file created with the DLL to the Fortran project and make the DLL available to the Fortran .EXE (by copying it to the .EXE's folder). P.S. I use Compaq Visual Fortran compiler.
C++ code
------------
// FortrancallsCPP.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include "iostream.h"
extern "C" { __declspec(dllexport) int read_ras_format(char* in_fileName, int fileName_length); };
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call,LPVOID lpReserved )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
};
// This is an example of an exported function.
int read_ras_format(char* in_fileName, int fileName_length)
{
cout<<"in_fileName: "<< in_fileName<<"n fileName_length: "<<<"n";
return 1;
};

Fortran code
-------
!****************************************************************************
!
! PROGRAM: fcallsCPP
!
! PURPOSE: Example of Fortran calling C++
!Since the C++ function in a DLL calls cout, and since the DLL
!is linked using single threaded DLL libraries, this Fortran
!project should be linked using the same libraries if you want
!the cout output to appear in the console window.
!
!****************************************************************************

PROGRAM CALL_DLL
IMPLICIT NONE
! VARIABLES
CHARACTER*33 SFILENAME
INTEGER RETURNVALUE

INTERFACE
INTEGER FUNCTION READ_RAS_FORMAT(SFILENAME, LENGTH)
!DEC$ ATTRIBUTES DLLIMPORT,ALIAS:'_read_ras_format' :: READ_RAS_FORMAT
!DEC$ ATTRIBUTES REFERENCE :: SFILENAME
!DEC$ ATTRIBUTES VALUE :: LENGTH
CHARACTER*33 SFILENAME
INTEGER LENGTH
END FUNCTION READ_RAS_FORMAT
END INTERFACE

PRINT *, 'HELLO WORLD'

! Body of simple_dll_test
!Note: you do not need to double up on the back slashes in a character string if
!you explicitly add the null-terminator character to a string. Only if you use the

!"dkjv\akdj\vd"C format does the compiler need to be told that the first backslash

!in each pair is to be kept and that it is not the signal for a special control character
!
SFILENAME = 'E:tempSHA00200604010046RF.ras' // CHAR(0)
RETURNVALUE = read_ras_format(SFILENAME, LEN_TRIM(SFILENAME))

END PROGRAM

0 Kudos
Reply