bonjour wil4linux
Faux .Le "Type" fortran permet d'inclure tous type de fields :double,character ,bool ,y compris un autre "type" comme en C#......
Vire cet exemple de  code VS parce que c'est un code specifique à VB6 ou une structure s'appelle "Type" (mot cle type vb6) 
Ce "type" de VB6 transparent pour les users est en fait un tableau SafeArray win32 ou BSTR(tableau auto-descriptif)......
En fait tu peux simplement utiliser un struc ou meme un class de C#.....qui se "mappe" (correspond) parfaitement au  "Type" du fortan  mais en respectant les contraintes d'alignement et de marshalling des types......
Relativement à ton code voici les observations :
1/methode P/Invoke:
- appel StdCall
- passer tjrs les args par reference(fortran ne connait pas le passage par valeur)
- exception tableau:  "ref" en C# ne s'utilise pas sur un tableau ,car un  tableau est toujours passe par reference par defaut (ptr sur le 1er element du tableau)....Si tu mets un ref c'est l'adresse du ptr que tu transmets d'ou acces memory violation....
- Vu cet exception si  on veut une valeurs de retour (comme avec un ref) prefixer tableau avec  prefixes "In,Out" (ils ont ete crees pour ca). 
=>Ils existent aussi cote fortran
2/marshalling de struc   
- meme alignement structure  (2,4,8 octet) cotes C# et fortran 
  =>Utiliser Directive  c# pack=8)  cote  Fortran ! Dec pack: 8 
  =>Uiliser  directive Layout.Sequentiel  C#  cote fortan "sequence"
- string fortran  => array de char ANSI(1 octet) et un string  C# ) => array de char  Unicode(2 octet). 
=>Specifie au marshaleur CharSet=ANSI cote C#....
 
- le struct ou class doit comporter un ctor d'initilisation avec  initialisation des tous ses membres.
Moyennant ces precautions on peut  passer n'importe quoi à fortran.. un struct ,un class ou un array de struc C#  ou de class tres simplement :
Voici un exemple qui passe un array de struct au fortan ,modifie les valeurs et les renvoies à C#...
fichier code  "type_struc.f90" du module fortran (declaration de la structure):
	
	1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
   |  
MODULE type_struc
   !
   ! C# Declaration
   !  //Simple struct C#
   !     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)]
   !     public struct SimpleStruct
   !     {
   !		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
   !        public String FileName;
   !
   !        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
   !        public String FilePath;
   !
   !	    [MarshalAs(UnmanagedType.I2)]
   !	    public short TotalShort;
   !	
   !	    [MarshalAs(UnmanagedType.R8)]
   !	    public double TotalDouble;
   !	
   !	    //Iniatiliser les fields et props du struc
   !	    public SimpleStruct(bool dummyargs)
   !	    {
   !	         FileName = String.Empty;
   !	         FilePath = String.Empty;
 !	             TotalShort = 0;
!	             TotalDouble = 0.0;
!	            }
!	        }
   !--------------------------------------------------------------------
   IMPLICIT NONE
 
 
   !Declaration du Type 
   !Pas de probleme avec les tableaux de caracteres "Ansi"
   !comme en C ou C++
   !note le pack 8 et le sequence (sequential du c#)
 
   ! dec$ pack : 8
   TYPE SimpleStruct
      SEQUENCE
   	  CHARACTER*100 :: FileName
	  CHARACTER*255 :: FilePath
	  INTEGER*2     :: TotalShort
	  REAL*8     :: TotalDouble
 
   END TYPE SimpleStruct
 
 END MODULE type_struc | 
 fichier code "ArrayFortranType.f90" du subroutine fortran appele qui utilise le module precedent  type_struc:
	
	1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
   |  
! Subroutine ArrayFortranType
!   Parametre:
!     arrStruct:  => tableau de type SimpleStruct passe 
!	  num_elem:   => nbre  d'elements dans le tableau
 
 
   SUBROUTINE ArrayFortranType(arrStruct, num_elem)
   !DEC$ ATTRIBUTES DLLEXPORT ::  ArrayFortranType
   !DEC$ ATTRIBUTES ALIAS :'ArrayFortranType' :: ArrayFortranType
 
   USE type_string
 
 
   IMPLICIT NONE
 
   !Prefixes IN OUT car passe par "ref"
   INTEGER*4   ,INTENT(INOUT):: num_elem
 
   !Prefixes IN OUT pour avoir une valeur de retour
   'Index base des tableaux Fortran => 1
 
   TYPE(SimpleStruct), INTENT(INOUT):: arrStruct(1:num_elem)
 
   LOGICAL ::  bstatus
   INTEGER :: i, j, k			! Loop variables
 
 
 
!dec$ if defined (DEBUG)
! Pour besoin de deboggage fenetre console ....
 
	bstatus = AllocConsole()
 
	WRITE (6, *) "Info from arrStruct"
	DO i = 1 , num_elem
 
		WRITE (6, *)  arrStruct(i).FileName
		WRITE (6, *)  arrStruct(i).FilePath
		WRITE (6, *)  arrStruct(i).TotalShort
		WRITE (6, *)  arrStruct(i).TotalDouble
 
	END DO
!dec$ endif	
 
! Now, fill in the fields FileName,FilePath, TotalShort,TotalDouble
 
 
		DO i = 1, num_elem
 
			arrStruct(i).FileName = 'FileName fortran'
			arrStruct(i).FilePath = 'FilePath fortran' 		
 
			arrStruct(i).TotalShort = arrStruct(i).TotalShort*10
			arrStruct(i).TotalDouble = arrStruct(i).TotalDouble*10.0
 
 
	    END DO
 
 
 
!dec$ if defined (DEBUG)
	bstatus = FreeConsole()
!dec$ endif
 
RETURN
END SUBROUTINE  | 
 a compiler en un fichier projet fortan "TestStruc.dll"
fichier code behind .cs du form appelant...:
	
	1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
   |  
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
 
namespace WinArrayStructFortran
{
    public partial class frmArrayStruct : Form
    {
        StringBuilder sb;
        public SimpleStruct ss;
 
        //notre Array struct
        public  int nbElem = 5;
        public SimpleStruct[] arrStruct;
        public frmArrayStruct()
        {
            InitializeComponent();
        }
        private void btnCalcul_Click(object sender, EventArgs e)
        {
 
        }
        private void btnArrayStruct_Click(object sender, EventArgs e)
        {
 
            // Fill the struct
 
            arrStruct = new SimpleStruct[nbElem];
            listBox1.Items.Clear();
            sb = new StringBuilder(); 
 
            for (int i = 0; i < nbElem; i++)
            {
                sb.Clear();
                ss = new SimpleStruct();
                ss.FileName = "mon fichier " + (i + 1).ToString();
                ss.FilePath = "mes/documents/" + (i + 1).ToString();
                ss.TotalShort = 15;
                ss.TotalDouble = 50.15;
                arrStruct[i] = ss;
                sb.Append(ss.FileName + "; " + ss.FilePath + ";" + ss.TotalShort + ";" + ss.TotalDouble + Environment.NewLine);
                listBox1.Items.Add(sb);
            }
 
            // CallingL 
            ArrayFortranType(arrStruct, ref nbElem);
 
            // Display result
 
            listBox2.Items.Clear();
            listBox2.Items.Add(nbElem );
            for (int i = 0; i < arrStruct.Length ; i++)
            {
                sb.Clear();
                ss = arrStruct[i];
                sb.Append(ss.FileName.Trim() + "; " + ss.FilePath.Trim() + ";" + ss.TotalShort + ";" + ss.TotalDouble + Environment.NewLine);
                listBox2.Items.Add(sb);
            }
            sb.Append(ss.FileName + "; " + ss.FilePath + ";" + ss.TotalShort + ";" + ss.TotalDouble + Environment.NewLine);
        }
        private void btnExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }
 
 
        /*     Declaration methode P/INVOKE        */
        //Convention d'appel StdCall
        //pas de ref devant arrayStruct mais prefixe [In, Out]
 
        [DllImport("TestStruc.dll",
            EntryPoint = "ArrayFortranType",
            CharSet = CharSet.Ansi,
            CallingConvention = CallingConvention.StdCall)]
        public static extern void ArrayFortranType(
        [In, Out] [MarshalAs(UnmanagedType.LPArray,ArraySubType=UnmanagedType.Struct)] SimpleStruct[] arrStruct,
        [In, Out] ref int Num_Elem);
 
 
 
 
    }
 
    /*     Declaration Simple struct C#       */
    //note le CharSet.Ansi & le Pack = 8
 
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)]
    public struct SimpleStruct
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
        public String FileName;
 
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
        public String FilePath;
 
        [MarshalAs(UnmanagedType.I2)]
        public short TotalShort;
 
        [MarshalAs(UnmanagedType.R8)]
        public double TotalDouble;
 
        //NB:Iniatiliser les fields et props du struc
        public SimpleStruct(bool dummyargs)
        {
            FileName = String.Empty;
            FilePath = String.Empty;
            TotalShort = 0;
            TotalDouble = 0.0;
        }
    }
} | 
 Tu peux meme passer un array de Class si tu le souhaites va....
bon code....
 
			
		
Partager