IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

passage d'un array de int en interrop


Sujet :

C#

  1. #1
    Membre émérite
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Points : 2 498
    Points
    2 498
    Par défaut passage d'un array de int en interrop
    Bonjour

    Je suis occupé a traduire un vieux code vb6 en C#.

    J'ai actuellement un souci de passage d'un array de int a une dll C

    Voici le code original VB

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Declare Function S7RdDB& Lib "PCS7LW32.dll" (pS7 As S7, ByVal DBNr%, ByVal ABWort%, ByVal WortAnz%, DstBuf As Any)
     
    Dim Buf(0 To 512) As Integer
     
      Res = S7RdDB(Ag, 120, 20, 20, Buf(0))
    Et voici comment je l'ai traduit

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        [DllImport("PCS7LW32.dll")]
        static public unsafe extern int S7RdDB(S7 pS7, int DBNr, int ABWort, int WortAnz, ref int[]DstBuf);
     
        public int[] Buf = new int[512];
     
        int Res = Pcs7lw32.S7RdDB(Ag, 120, 20, 20, ref Buf);
    J'ai vraissemblablement un souci avec la declaration ou le passage de Buf

    Quelqu'un aurait il une suggestion ?

    Merci de votre aide

  2. #2
    Membre émérite
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Points : 2 498
    Points
    2 498
    Par défaut
    Bonjour

    Apres quelques test, il semble que j'ai avant tout un problème avec le passage du type S7

    Voici le code VB

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    Type S7
      Com      As Integer
      bInit    As Byte
     
      DummyB1   As Byte
     
      DummyB2   As Integer
      Err      As Integer
      Internal(1 To 1600) As Byte
    End Type
     
     
     
    Declare Function S7Init& Lib "d:\projets\jooli\Recutex\Usine\SourceVB\Capteren\PCS7LW32.dll" (pS7 As S7, ByVal Com%, ByVal SPSMPIAdr%, ByVal LocalMPIAdr%, ByVal Baud%)
     
      bInit = S7Init(Ag, Ag.Com, 2, 13, 19200)
    Et la traduction C# que j'en ai faite

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
      public class S7
      {
        public int Com;
        public byte bInit;
     
        public byte DummyB1;
     
        public byte DummyB2;
        public int Err;
        public byte[] Internal;
        public S7()
        {
          Com = 0;
          bInit = 0;
          DummyB1 = 0;
          DummyB2 = 0;
          Err = 0;
          Internal = new byte[1600];
        }
      }
     
     
       [DllImport("PCS7LW32.dll")]
       static public unsafe extern int S7Init(S7 pS7, int Com, int SPSMPIAdr, int LocalMPIAd, int Baud);
     
     
       S7 Ag = new S7();
       int bInit = Pcs7lw32.S7Init(Ag, Ag.Com, 2, 13, 19200);

    Si j'execute un VB ca passe et le byte bInit du Type S7 prends la valeur 1

    Si j'execute en C#, ca passe aussi mais le byte bInit de la classe S7 reste a zero

    Il y a donc certainement un problème de referece a la classe S7 par rapport au type S7 de VB

    Merci de votre aide

  3. #3
    Membre émérite
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Points : 2 498
    Points
    2 498
    Par défaut
    Bonjour

    J'ai continué mes investigations et j'ai découvert qu'un Integer en VB6 est un Short en C#

    J'ai donc adapté mon appel et ma classe S7 pour mettre des short a la place des int : pas plus de résultat
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
      public class S7
      {
        public short Com;
        public byte bInit;
     
        public byte DummyB1;
     
        public byte DummyB2;
        public short Err;
        public byte[] Internal;
     
     
        public S7(int a) 
        {
          Com = 0;
          bInit = 0;
          DummyB1 = 0;
          DummyB2 = 0;
          Err = 0;
          Internal = new byte[1600];
        }
      }
    J'ai alors truqué pour remplacer la classe S7 par un array de byte



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        [DllImport("PCS7LW32.dll")]
        static public unsafe extern short S7Init(IntPtr pS7, short Com, short SPSMPIAdr, short LocalMPIAd, short Baud);
     
     
          byte[] xx = new byte[1607];
     
          GCHandle pinnedArray = GCHandle.Alloc(xx, GCHandleType.Pinned); 
          IntPtr pointer = pinnedArray.AddrOfPinnedObject(); 
          int bInit = Pcs7lw32.S7Init(pointer, Ag.Com, 2, 13, 19200);
    Et là : MIRACLE l'appel se passe bien et je peux constater que le troisieme byte a pris la valeur 1 ce qui correspond bien a ce que j'attends

    Mais comment faire pour passer directement la classe et pas truquer avec un array de byte ?

  4. #4
    Modérateur

    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 722
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 722
    Points : 5 100
    Points
    5 100
    Par défaut
    Bonjour,

    Il me semble que pour l'interrop il faut utiliser une structure pour le passage de parramètre et pas une classe.

    La structure est passé par valeur (comme ton tableau de byte) alors que la classe est passé par référence.
    Pourtant cela ne semble pas correspondre aves ton test. Je doute du coup.

    Integer correspond à short
    Long correspond à int


    A+, Hervé.

  5. #5
    Membre émérite
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Points : 2 498
    Points
    2 498
    Par défaut
    Merci Hervé

    Il y a de l'idée
    Si je passe une Sructure S7 au lieu d'une classe et que je la passe en ref alors effectivement bInit est correctement assigné mais par contre mon tableua de byte []Internal devient null

    Il y a donc toujours un bingz

    Et si je je passe une Classe S7 en Ref alors l'application s'interromp directement (grosse corruption sans doute)

  6. #6
    Membre émérite
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Points : 2 498
    Points
    2 498
    Par défaut je pense avoir trouvé
    Apres de nombreuses investigations je pense qu'il faut effectivement passer une Structure qui correspond au Type VB6
    Qu'il faut la passer en ref
    Et qu'il faut la declarer unsafe pour declarer le tableau de byte en fixed (du coup plus besains d'un constructeur pour l'allocation)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
      public unsafe struct S7
      {
        public short Com;
        public byte bInit;
     
        public byte DummyB1;
     
        public byte DummyB2;
        public short Err;
        public fixed byte Internal[1600];
     
      }
    Je m'attaque maintenant au passage de l'array de int qui sont devenu des short

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Declare Function S7RdDB& Lib "PCS7LW32.dll" (pS7 As S7, ByVal DBNr%, ByVal ABWort%, ByVal WortAnz%, DstBuf As Any)
     
    Dim Buf(0 To 512) As Integer
     
      Res = S7RdDB(Ag, 120, 20, 20, Buf(0))

  7. #7
    Modérateur

    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 722
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 722
    Points : 5 100
    Points
    5 100
    Par défaut
    Citation Envoyé par olibara Voir le message
    Je m'attaque maintenant au passage de l'array de int qui sont devenu des short

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Declare Function S7RdDB& Lib "PCS7LW32.dll" (pS7 As S7, ByVal DBNr%, ByVal ABWort%, ByVal WortAnz%, DstBuf As Any)
     
    Dim Buf(0 To 512) As Integer
     
      Res = S7RdDB(Ag, 120, 20, 20, Buf(0))
    Attention, au niveau du code vb seulement le premier élément du tableau "Buf(0)" est passé en paramètre.
    Après je ne sais pas ce que tu souhaites faire.

  8. #8
    Membre émérite
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Points : 2 498
    Points
    2 498
    Par défaut
    Salut Hervé

    Non a mon avis dans le code VB on passe le premier element du tableau en tant que reference du tableau lui meme et les deux entiers (ByVal ABWort%, ByVal WortAnz%) : 20, 20 donnent les tailles utilisable

    Donc je dois encore trouver le moyer de traduire cela

  9. #9
    Expert confirmé
    Inscrit en
    Avril 2008
    Messages
    2 564
    Détails du profil
    Informations personnelles :
    Âge : 64

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 564
    Points : 4 442
    Points
    4 442
    Par défaut
    bonjour Olibara
    Any en vb6 c'est un Object ce qui permet de passer la variable par reference.....
    Comme la variable est un tableau ,en vb6 on passe le 1er element du tableau qui est l'adresse de l'objet Tableau et en parametre on indique un Object (ce qui est cense permettre au compilateur d'en deduire le type & la taille de l'objet et evite de passer les dimensions).....
    En .Net Any a comme equivalent Object en VB.Net ....mais il faut le "marshaller" pour aider le "marshallr" et eviter du code unsafe........

    regarde cette rubrique MSDN DOC ou tous les types API Win32 et Com sont passes en revue:
    Rubrique UnmanagedType, énumération :
    AsAny Type dynamique qui détermine le type d'un objet au moment de l'exécution et marshale l'objet comme ce type. Valide uniquement pour les méthodes d'appel de plate-forme.

    code equivalent en vb.net :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    Imports System.Runtime.InteropServices
    Public Class Form1
        <DllImport("PCS7LW32.dll")> _
        Public Shared Function S7RdDB(<MarshalAsAttribute(UnmanagedType.AsAny)> _
            ByVal DstBuf As Object) As Integer
        End Function
        Public Sub New()
     
            ' Cet appel est requis par le concepteur.
            InitializeComponent()
     
            ' Ajoutez une initialisation quelconque après l'appel InitializeComponent().
            Dim Buf(0 To 512) As Integer
            'on passe l'adresse du 1er element de "tout le bloc objet memoire tableau"
            'et le marshaler calculera la taille............Intricacies ou intrications du .Net  
            Dim Res As Integer = S7RdDB(Buf(0))
        End Sub
    code Csharp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    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 OlibaraAsAny
    {
        public partial class Form1 : Form
        {
            [DllImport("PCS7LW32.dll")]
            public static int S7RdDB([MarshalAsAttribute(UnmanagedType.AsAny)] Object DstBuf);
     
            public Form1()
            {
                InitializeComponent();
     
                //code parfaitement legitime en C#
     
                int[] Buf = new int[513] ;
     
                int  Res = S7RdDB(Buf[0]);
     
     
            }
        }
    }
    Cela a entre autres avantages d'eviter le dilemne de passage des dimensions des tableaux aux fonctions API C quand les arguments de la fonction ne comportent pas les dites dimensions....
    Les vieux programmeurs en VB6 s'en sortaient avec Any ......
    bon code...................

  10. #10
    Membre émérite
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Points : 2 498
    Points
    2 498
    Par défaut
    Merci Mabrouki

    Pour le moment je passe mon array de short et ca ne semble pas poser de souci

Discussions similaires

  1. Réponses: 5
    Dernier message: 22/01/2014, 20h56
  2. Transforrmer un int en array de int
    Par olibara dans le forum C#
    Réponses: 1
    Dernier message: 10/11/2008, 08h59
  3. [Tableaux] Passage d'un Array via method POST
    Par elagarde dans le forum Langage
    Réponses: 10
    Dernier message: 30/10/2008, 16h50
  4. Réponses: 2
    Dernier message: 20/08/2008, 09h05
  5. [XI] Passage de paramètre (Array)
    Par jouberts dans le forum SAP Crystal Reports
    Réponses: 1
    Dernier message: 11/07/2007, 10h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo