Table of contents
The document describes how to generate a LinkableComponent on Linux:
- how to compile a shared library for a Fortran 90 engine named <engine>
- how to port a C# wrapper for this shared library from Windows to Linux. The wrapper contains a class for accessing the Fortran dll <engine>DllAccess and two outer classes <engine>DotNetAccess and <engine>Wrapper, see Migrating existing Fortran based models codes
2. Technical prerequisites
2.1. Machine and OS of the test system
- workstation with an Intel Xeon processor
- 64bit Suse Linux Edition Desktop SLED 10.3 on the machine with the Fortran compiler
- 64bit openSUSE 11.0 on the machine with the C# compiler
2.2. Mono for multi platform C#
- Mono v. 1.9.1. for openSUSE 11.0 in 64 bit mode. V. 1.9.1. is the concrete term, but it is also referred to as Mono 2.0.
- compiler gmcs 2.0.
2.3. Fortran 90 Compiler
- Intel 64 bit Fortran Compiler v. 9.1.051
3. How to generate a shared library for a Fortran engine
During runtime the C# wrapper refers only one Fortran shared library. All Fortran sources were compiled to one shared library <fortranEngine>.so:
Linking the compiled objects:
During runtime some fortran libraries must be accessible via the environment variable LD_LIBRARY_PATH. In the following examples they are provided by the ifort compiler.
3.2. Ifort parameter bug
The ifort compiler v. 9.1.051 has a bug with public character parameters in modules.
The parameter c_att_name can easily be accessed from an external Fortran method. But if a Mono C# application calls a Fortran method, that accesses c_att_name, it will crash without error message. The solution is a Fortran function, that exports the parameter as a return value. Now the values can be accessed from C#.
3.3. Fortran interface functions
The <fortranEngine>.so interface functions are the same as in Windows Fortran. The two example functions are part of the module gei_ui and will be accessed from C# in 4.2.1.. The first one returns the integer comp_id_len.
The second example returns the character string comp_id.
4. How to port a C# wrapper from Windows to Linux
The Mono Guidelines Interop with Native Libaries gives general information about the interface between managed and unmanaged code.
The wrapper has three layers:
- <engine>DllAccess.cs is the inner class for accessing the Fortran dll;
- <engine>DotNetAccess.cs references <engine>DllAccess.cs;
- <engine>Wrapper.cs is a LinkableComponent and the outer layer.
Compilation of the two inner layers:
Compilation of the outer layer:
4.2. How to port the individual layers
Fortunately, the original Windows C# code can nearly remain as it is.
<engine>DllAccess offers access to the Fortran shared library, e.g. @"gei.xe.so". The most of the Windows C# code remains unchanged and is displayed in black colour in the following example. The Fortran module gei_ui, method gei_component_id_len returns the integer comp_id_len.
Some more adjustments are necessary, if a Fortran method returns the character string quantId:
[Out] byte[ ] quantId:
Several guidelines recommend to marshall a variable of type StringBuilder in order to return a Fortran character string:
But on Linux systems StringBuilder can very rarely lead to variables with undefined return values. It is not clear why this happens. The Mono guidelines display a slightly different case, where the Mono garbage collector frees memory before the character string is returned, s. paragraph "GC-Safe P/Invoke code".
However, the variables of type [Out] byte[ ] were always returned correctly and it is recommended to use them on Linux. The StringBuilder remains the better solution for Windows .NET. Developers are invited to find a solution that works on Windows as well as on Linux, e.g. an additional C / C++ wrapper or a SWIG generated wrapper.
Methods accessing int variables, e.g. ComponentIdLen(), remain unchanged from Windows:
This example displays that the variable of type byte[ ] from 4.2.1. is externally encoded to the string str:
Furthermore, the Initialize method of this class is a good place for a check, whether the dll is running on Mono or not:
There are no changes compared to Windows C#.
5. Use of the LinkableComponent
Before using the LinkableComponent its location must be known by Linux. It is recommended to put all shared libraries <fortranEngine>.so, <engine>DotNetAccess.dll and <engine>Wrapper.dll in one directory <componentDir>.
Now the generated LinkableComponent can be connected to any other LinkableComponent. Adding it as a model to the Linux version of the ConfigurationEditor is an easy test, s. How to port the OpenMI from Windows to Linux.