C# Array to Fortran

C# Array to Fortran

Hello,

I try to pass an 1D-array from a C#-DLL to Fortran. For that I am using R. Giesecke DllExport. That makes my managed DLL to a unmanaged DLL with a .lib file. To pass a normal parameter works well. Please see here: https://software.intel.com/en-us/forums/topic/517631

The 1D-Array has always the size of 6! The size of the array will never change only the assigned value.

Here my Code in C#:

using System;
using System.Text;
using RGiesecke.DllExport;
using System.Runtime.InteropServices;

namespace Testme
{
    class Test
    {
        [DllExport("Get1DArray", CallingConvention = CallingConvention.Cdecl)]
        public static int Get1DArray([MarshalAs(UnmanagedType.LPArray, SizeConst = 5)] int [] Stress)
            
        {
           
            Stress [0] = 0;
            Stress [1] = 1;
            Stress [2] = 2;
            Stress [3] = 3;
            Stress [4] = 4;
            Stress [5] = 5;

            return Stress[5];
        }

    }
}

Build my C# Dll successfully.

Here my Fortran Code:

MODULE MYEXTERNALS
USE iso_c_binding
INTERFACE
FUNCTION Get1DArray(Stress) RESULT(ret) bind(c, name="Get1DArray")
USE, intrinsic :: iso_c_binding
INTEGER(c_int), intent(in) :: Stress(6)
INTEGER(c_int) :: ret
END FUNCTION
END INTERFACE
END MODULE MYEXTERNALS


PROGRAM CallArray
!DEC$ATTRIBUTE DLLIMPORT :: Get1DArray
USE MYEXTERNALS
IMPLICIT NONE
PRINT*, '1DArray =', Get1DArray(Stress)
PAUSE
END PROGRAM CallArray

I get following error:

error #6404: This name does not have a type, and must have an explicit type.   [STRESS] 

Please help me... Thanks in advance!

- Carsten

 

9 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Try SizeConst=6 in your C# marshaling attribute.

Best Reply

We do not need to look at anything beyond the Fortran code to resolve the problem. The variable "stress" is not declared in the main program. Although there is information in the interface declaration about the argument to the function, the name itself is not a module variable and is not available through the USE statement in the main program. 

Add a type declaration for the variable. You also need to move the DLLIMPORT directive into the interface block.

For your testing (I do not have the Giesecke stuff to do so myself):

MODULE MYEXTERNALS
USE iso_c_binding
INTERFACE
FUNCTION Get1DArray(Stress) RESULT(ret) bind(c, name="Get1DArray")
!DEC$ATTRIBUTES DLLIMPORT :: Get1DArray
USE, intrinsic :: iso_c_binding
INTEGER(c_int), intent(in) :: Stress(6)
INTEGER(c_int) :: ret
END FUNCTION
END INTERFACE
END MODULE MYEXTERNALS


PROGRAM CallArray
USE MYEXTERNALS
IMPLICIT NONE
INTEGER(c_int) :: Stress(6)
PRINT*, '1DArray =', Get1DArray(Stress)
PAUSE
END PROGRAM CallArray

 

Stress is not declared in PROGRAM CallArray perhaps?

 

 

Hey,

mecej4 thanks for posting the modiefied Code!

I tried it and get following:

And my Output says:

'CallArrayDll.exe': Loaded '\\cifs\cluster\Home\ca416444\WinDocuments\Masterarbeit\C# Dllexport\to Fortran\1DArray2\CallArrayDll\Debug\CallArrayDll.exe', Symbols loaded.
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\ntdll.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\kernel32.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\KernelBase.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded '\\cifs\cluster\Home\ca416444\WinDocuments\Masterarbeit\C# Dllexport\to Fortran\1DArray2\CallArrayDll\Debug\ArrayDll.dll', No native symbols in symbol file.
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\mscoree.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\imagehlp.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\msvcrt.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\advapi32.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\sechost.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\rpcrt4.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\sspicli.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\cryptbase.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscoreei.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\shlwapi.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\gdi32.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\user32.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\lpk.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\usp10.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\imm32.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\msctf.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\msvcr110_clr0400.dll', Cannot find or open the PDB file
First-chance exception at 0x75c8c42d in CallArrayDll.exe: 0x04242420: 0x4242420.
'CallArrayDll.exe': Loaded 'C:\Windows\assembly\NativeImages_v4.0.30319_32\mscorlib\ce5f61c5754789df97be8dc991c47d07\mscorlib.ni.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded '\ArrayDll.dll', No symbols loaded.
'CallArrayDll.exe': Unloaded '\ArrayDll.dll'
'CallArrayDll.exe': Loaded '\ArrayDll.dll', No symbols loaded.
'CallArrayDll.exe': Loaded 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\clrjit.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\oleaut32.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\ole32.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\diasymreader.dll', Cannot find or open the PDB file
First-chance exception at 0x75c8c42d in CallArrayDll.exe: Microsoft C++ exception: EEException at memory location 0x0020f4fc..
First-chance exception at 0x75c8c42d in CallArrayDll.exe: 0xE0434352: 0xe0434352.
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\dbghelp.dll', Cannot find or open the PDB file
'CallArrayDll.exe': Loaded 'C:\Windows\SysWOW64\clbcatq.dll', Cannot find or open the PDB file
The thread 'Win32 Thread' (0x5d4c) has exited with code 3 (0x3).
The thread 'Win32 Thread' (0x3944) has exited with code 3 (0x3).
The thread 'Win32 Thread' (0x59fc) has exited with code 3 (0x3).
The program '[24492] CallArrayDll.exe: Native' has exited with code 3 (0x3).

I cannot help you with the C# part, especially since you are using third party glue. The following C source does the same as your C# function, and it works fine when I create a DLL from it and call it from the Fortran code above.

The point of view one adopts with the C Interops of Fortran is that things should work when the companion C processor is used upon code which, at run time, behaves in a defined way that is based on how C compilers commonly function. The subroutine/function code with the BIND(C) attribute is usually written in C, but it could be written in C#, assembly or even Fortran, as long as the compiled code behaves in the same way as C code. Thus, your task is reduced at this point to writing C# code that functions in a manner equivalent to code compiled from the C function below.

int Get1DArray(int Stress[]){
   Stress[0]=0; Stress[1]=1; Stress[2]=2;
   Stress[3]=3; Stress[4]=4; Stress[5]=5;
   return Stress[5];
   }

Here is the transcript from the build and run on W8.1 X64, using the 64-bit IFort 14.0.3 compiler:

S:\lang>icl /LD cstress.c /link /export:Get1DArray
Intel(R) C++ Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 14.0.2.176 Build 20140130
Copyright (C) 1985-2014 Intel Corporation.  All rights reserved.

cstress.c
Microsoft (R) Incremental Linker Version 11.00.61030.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:cstress.dll
-dll
-implib:cstress.lib
/export:Get1DArray
cstress.obj
   Creating library cstress.lib and object cstress.exp

S:\lang>ifort stress.f90 cstress.lib
Intel(R) Visual Fortran Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 14.0.3.202 Build 20140422
Copyright (C) 1985-2014 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 11.00.61030.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:stress.exe
-subsystem:console
stress.obj
cstress.lib

S:\lang>stress
 1DArray =           5
Fortran Pause - Enter command<CR> or <CR> to continue.

 

Thank you mecej4! Helped me a lot... Now I know where to look.

It works... I created a new solution with the Fortran Code of mecej4. I have no idea why it has not worked previously. In the solution before I have probably played around too much.

How can I pass the hole array. And not only one element?

Quote:

Carsten A. wrote:

...

How can I pass the hole array. And not only one element?

How about adding the array to the parameter list in your C# Get1DArray procedure and passing it "by ref"?  Get1DArray could even be a void procedure (i.e., SUBROUTINE on the Fortran side).

By the way, will it be possible for you to elaborate on your use case of consuming "static" C# procedures from Fortran?  Often the need is in other direction i.e., it is Fortran that usually has a library of "static" procedures and which need to be called from some C# application.  Unless one has already built a large code of "static" methods in C#, won't it be better to create a library of such methods in a "native" language such as C, C++, Fortran, etc. instead of C#?  On the other hand, given the object-oriented base of .NET Framework and ease-of-use, there are now a gigantic number of valuable classes in C# (e.g. data/image processing, etc.) that one may want to consume in Fortran.  Does the R. Giesecke DllExport work in such situations i.e., for "instances"/"objects", not static methods? 

Leave a Comment

Please sign in to add a comment. Not a member? Join today