- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Try SizeConst=6 in your C# marshaling attribute.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Stress is not declared in PROGRAM
CallArray perhaps?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you mecej4! Helped me a lot... Now I know where to look.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page