...
The document describes how to generate a LinkableComponent on Linux:
- how to compile a shared library for a Fortran 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.
...
Panel | ||||
---|---|---|---|---|
| ||||
ifort -c -fPIC -convert big_endian -fpp *.f90 |
...
Panel | ||||
---|---|---|---|---|
| ||||
ifort -shared *.o -o <sharedLibrary.so> |
...
Panel | ||||
---|---|---|---|---|
| ||||
export LD_LIBRARY_PATH=/opt/intel/fce/9.1.051/lib:. // on 64bit systems |
2.2. Ifort parameter bug
...
The ifort compiler v. 9.1.051 has a bug with public character parameters in modules.
Example:
...
...
CHARACTER (LEN=40), PUBLIC, PARAMETER :: c_att_name(2)= &
/ 'title ', &
'history '/
The ifort compiler v. 9.1.051 has a bug with public character parameters in modules.
Panel | ||||
---|---|---|---|---|
| ||||
The parameter c_att_name can not be accessed from outside the module. The solution is a function that exports the parameter as a return value. Now the values can be accessed from outside.
Panel | ||||
---|---|---|---|---|
| ||||
PUBLIC FUNCTION get_c_att_name ( idx ) & |
...
- <engine>DllAccess.cs is the inner layer;
- <engine>DotNetAccess.cs;
- <engine>Wrapper.cs is a LinkableComponent and the outer layer.
Compilation of the two inner layers:
Panel | ||||
---|---|---|---|---|
| ||||
gmcs -target:library -out: <engine>DotNetAccess.dll <engine>DllAccess.cs |
Compilation of the outer layer:
Panel | ||||
---|---|---|---|---|
| ||||
gmcs -target:library -out:<engine>Wrapper.dll -pkg:baw-geidotnet.pc, |
3.2. Changes from Windows to Linux
Fortunately, the original Windows C#-Code can remain nearly as it is.
3.2.1. Changes in <engine>DllAccess.cs
Most part of the original Windows code remains unchanged, as displayed in the example, where the Fortran method component_id_len returns
comp_id_len.
Panel | ||||
---|---|---|---|---|
| ||||
[DllImport(
|
Some more adjustments are necessary, if a Fortran method returns a character string:
Panel | ||||
---|---|---|---|---|
| ||||
[ DllImport( @"gei.xe.so",
|
The return of Fortran character strings (unmanaged code) to C# (managed Code) may cause a problem. Several guidelines recommend to marshall a variable of type StringBuilder:
Panel | ||||
---|---|---|---|---|
| ||||
MarshalAs(UnmanagedType.LPStr) StringBuilder quantId |
But StringBuilder may 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 Fortran part frees memory to early, http://www.mono-project.com/Interop_with_Native_Libraries, paragraph "GC-Safe P/Invoke code"
However, during the tests the byte variables were always returned correctly.
3.2.2.Changes in <engine>DotNetAccess.cs
The example displays that the byte array from 3.2.1. is externally encoded to the string str:
Panel | ||||
---|---|---|---|---|
| ||||
public string OutputExchangeQuantityId(int compIdx, int outputExchangeN) |
Furthermore the Initialize method of this class is a good place for a check, whether the dll is running on Mono or not:
Panel | ||||
---|---|---|---|---|
| ||||
if ( Type.GetType ("Mono.Runtime") == null ) |