Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1537 connectés 

  FORUM HardWare.fr
  Programmation
  C#/.NET managed

  melange de code .NET et natif

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

melange de code .NET et natif

n°1148285
theshockwa​ve
I work at a firm named Koslow
Posté le 12-07-2005 à 18:44:49  profilanswer
 

Voilà, je viens de m'apercevoir d'un léger problème que je rencontre ... Je ne suis toujours pas familier avec .Net, mais je ne perds pas espoir.
 
J'ai un projet en C# qui fait des appels à WMI (via System.Management.ManagementObjectSearcher) et tout se passe très bien. Seulement, dès que je fais un appel à ces fonctionnalités dans la méthode de gestion des messages systèmes (WndProc) de ma fenêtre, des exceptions inattendues sont levées. J'avais remarqué un problème similaire lorsque je tentais d'utiliser la libusb-win32 (écrite en C) ...
 
Cette découverte m'a amené à me poser des questions sur un autre morceau de code utilisant Python for .Net (ou plutôt tentant de l'utiliser) où j'avais un problème d'exceptions de ce genre.
 
Tout d'abord, il faut savoir que la lib Python for .Net remplace la fonction d'import de cpython (vu qu'elle s'appuye dessus) par une méthode C# afin d'intercepter les imports du type "import CLR.*" pour pouvoir importer des objets .Net en Python.  
 
Donc, schématiquement :
 
Appli C# : exécution d'une ligne python pour importer un script perso
 -> P.Net : appel de CPython
 -> CPython : appel de la fonction __import__ remplacée donc remontée dans P.Net
 -> P.Net : on réalise que l'import est "normal", donc on rappelle la méthode __import__ d'origine de cpython
 -> CPython : Exception levée !
 
Alors que le scénario suivant se déroule sans aucun problème :
 
Appli C# : appel de la fonction de remplacement d'__import__ de P.Net
 -> P.Net : on réalise que l'import est "normal" => CPython
 -> CPython : l'import de la lib se fait bien
 
Y aurait-il une subtilité à connaître au sujet des changements de contexte (.Net / natif) ? Car j'ai la forte impression que le problème survient dès qu'on a un enchainement du type Natif -> .Net -> Natif ...
 
un avis sur le sujet ? Une idée ?
 
 
Edit : typo ...


Message édité par theshockwave le 12-07-2005 à 18:45:17
mood
Publicité
Posté le 12-07-2005 à 18:44:49  profilanswer
 

n°1148367
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 12-07-2005 à 20:19:19  profilanswer
 

le mélange managed et natif est un casse tête incommensurable, mon plugin dans ma signature est un mix de ce genre (because plugin en C# et SDK de winamp en C), et c'est plus que casse couilles... surtout au niveau de la conversion des types.
faut jouer avec la classe Marshal, faire les allocs/désallocs à la main, etc... finalement, j'ai tout fait en C# unsafe (donc avec pointeurs). c'est crade, mais ça fonctionne et c'est bien moins prise de tête... mais bon, je suis quand même en train de virer le mode unsafe, trop incertain à long terme
c'est quoi les exceptions qui sont levées ?


---------------
J'ai un string dans l'array (Paris Hilton)
n°1148376
theshockwa​ve
I work at a firm named Koslow
Posté le 12-07-2005 à 20:46:24  profilanswer
 

je te dis ca demain, j'ai pas mon code sous la main, là

n°1148925
theshockwa​ve
I work at a firm named Koslow
Posté le 13-07-2005 à 12:10:22  profilanswer
 

Bon, j'ai un peu plus poussé ma recherche au sujet des problèmes évoqués plus haut ... Pour celui qui est relatif aux WMI, j'ai pu produire un fichier qui met en avant ce problème :
 

Code :
  1. using System;
  2. using System.Drawing;
  3. using System.Collections;
  4. using System.ComponentModel;
  5. using System.Windows.Forms;
  6. using System.Data;
  7. namespace ExceptionSample
  8. {
  9. public class Form1 : System.Windows.Forms.Form
  10. {
  11.  bool showDiskDrivesOnNextMessage = false;
  12.  private System.Windows.Forms.Button BtnThroughWndProc;
  13.  private System.Windows.Forms.Button BtnDirectCall;
  14.  private System.ComponentModel.Container components = null;
  15.  public Form1()
  16.  {
  17.   InitializeComponent();
  18.  }
  19.  protected override void Dispose( bool disposing )
  20.  {
  21.   if( disposing  && (components != null) )
  22.    components.Dispose();
  23.   base.Dispose( disposing );
  24.  }
  25.  #region Windows Form Designer generated code
  26.  /// <summary>
  27.  /// Required method for Designer support - do not modify
  28.  /// the contents of this method with the code editor.
  29.  /// </summary>
  30.  private void InitializeComponent()
  31.  {
  32.   this.BtnThroughWndProc = new System.Windows.Forms.Button();
  33.   this.BtnDirectCall = new System.Windows.Forms.Button();
  34.   this.SuspendLayout();
  35.   //  
  36.   // BtnThroughWndProc
  37.   //  
  38.   this.BtnThroughWndProc.Location = new System.Drawing.Point(0, 0);
  39.   this.BtnThroughWndProc.Name = "BtnThroughWndProc";
  40.   this.BtnThroughWndProc.Size = new System.Drawing.Size(144, 32);
  41.   this.BtnThroughWndProc.TabIndex = 0;
  42.   this.BtnThroughWndProc.Text = "WMI Through WndProc";
  43.   this.BtnThroughWndProc.Click += new System.EventHandler(this.BtnThroughWndProc_Click);
  44.   //  
  45.   // BtnDirectCall
  46.   //  
  47.   this.BtnDirectCall.Location = new System.Drawing.Point(0, 32);
  48.   this.BtnDirectCall.Name = "BtnDirectCall";
  49.   this.BtnDirectCall.Size = new System.Drawing.Size(144, 32);
  50.   this.BtnDirectCall.TabIndex = 1;
  51.   this.BtnDirectCall.Text = "WMI Direct Call";
  52.   this.BtnDirectCall.Click += new System.EventHandler(this.BtnDirectCall_Click);
  53.   //  
  54.   // Form1
  55.   //  
  56.   this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
  57.   this.ClientSize = new System.Drawing.Size(144, 69);
  58.   this.Controls.Add(this.BtnDirectCall);
  59.   this.Controls.Add(this.BtnThroughWndProc);
  60.   this.Name = "Form1";
  61.   this.Text = "Form1";
  62.   this.ResumeLayout(false);
  63.  }
  64.  #endregion
  65.  #region Methods
  66.  public static void showDiskDrives()
  67.  {
  68.   System.Management.ManagementObjectSearcher mos = new System.Management.ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive" );
  69.   foreach (System.Management.ManagementObject mo in  mos.Get())
  70.   {
  71.    string desc = "";
  72.    foreach(System.Management.PropertyData pd in mo.Properties)
  73.     if(pd.Value != null)
  74.      desc += pd.Name + "=" + pd.Value + "\r\n";
  75.     else
  76.      desc += pd.Name + "\r\n";
  77.    MessageBox.Show(desc);
  78.   }
  79.  }
  80.  protected override void WndProc(ref Message m)
  81.  {
  82.   switch(m.WParam.ToInt32())
  83.   {
  84.    case 0x8000: // New device connection (DBT_DEVICEARRIVAL)
  85.     showDiskDrives(); // raises an exception
  86.     break;
  87.    case 0x8004: // Removing a device (DBT_DEVICEREMOVECOMPLETE)
  88.     showDiskDrives(); // raises an exception
  89.     break;
  90.    default:
  91.     if(showDiskDrivesOnNextMessage)
  92.     {
  93.      showDiskDrivesOnNextMessage = false;
  94.      showDiskDrives(); // runs as expected
  95.     }
  96.     break;
  97.   }
  98.   base.WndProc (ref m);
  99.  }
  100.  #endregion
  101.  [STAThread]
  102.  static void Main()
  103.  {
  104.   Application.Run(new Form1());
  105.  }
  106.  private void BtnThroughWndProc_Click(object sender, System.EventArgs e)
  107.  {
  108.   showDiskDrivesOnNextMessage = true;
  109.  }
  110.  private void BtnDirectCall_Click(object sender, System.EventArgs e)
  111.  {
  112.   showDiskDrives(); // runs as expected
  113.  }
  114. }
  115. }


 
avec les références qui vont bien, évidemment ... Enjoy  :sol:  
NB : l'exception est levée lorsqu'on ajoute ou qu'on retire un périphérique (clé USB, par exemple)
 
Je retourne voir du côté de python for .Net de ce pas
 
Edit : légère épuration du code


Message édité par theshockwave le 13-07-2005 à 14:51:46
n°1148951
theshockwa​ve
I work at a firm named Koslow
Posté le 13-07-2005 à 12:35:58  profilanswer
 

theshockwave a écrit :

Appli C# : exécution d'une ligne python pour importer un script perso
 -> P.Net : appel de CPython
 -> CPython : appel de la fonction __import__ remplacée donc remontée dans P.Net
 -> P.Net : on réalise que l'import est "normal", donc on rappelle la méthode __import__ d'origine de cpython
 -> CPython : Exception levée !


 
 
En fait, ce n'est pas tout à fait vrai, le scénario serait plutôt le suivant :
 
Appli C# : exécution d'une ligne python pour importer un script perso
 -> P.Net : appel de CPython
 -> CPython : appel de la fonction __import__ remplacée donc remontée dans P.Net
 -> P.Net : on réalise que l'import est "normal", donc on rappelle la méthode __import__ d'origine de cpython
 -> CPython : chargement de la lib ok, remontée dans le code appelant
 -> P.Net : réception du pointeur sur la lib importée ok (même valeur que lorsqu'on fait l'import directement via la fonction de remplacement)
 ---------- remontée dans le code appelant du pointeur sur la lib
 -> CPython : levée d'une exception System.NullReferenceException
 
 
 
Ce qui est surprenant, c'est que ce genre de manip passe pour la console d'interprétation fournie par Zope (ce sont eux qui font Python for .Net) Enfin, en tout cas, lorsqu'on fait de simples imports, ca passe bien par leur "hook" pour ensuite revenir dans CPython, et ca ne lève pas d'exception :/

n°1148966
FlorentG
Posté le 13-07-2005 à 12:42:16  profilanswer
 

Ce qu'il faut éviter, c'est utiliser des ressources non-managées dans des classes où y'a des ressources managées. C'est là où ça devient galère et bordélique. Il vaut mieux faire une ch'tite classe qui wrap une ressource non-managées, qui implémentera IDisposable. On n'oubliera pas d'y mettre un finalizeur...

n°1149094
theshockwa​ve
I work at a firm named Koslow
Posté le 13-07-2005 à 14:35:53  profilanswer
 

oui, enfin ... Ce genre de classe est proposé directement par la lib python for .Net ... normalement, lorsque je récupère mon pointeur, je le fait passer en PyObject (avec le constructeur qui va bien) et je peux en tirer une lib avec des fonctions pour récupérer des symboles dedans, etc ... Le problème en lui-même est simplement que là, je ne peux même pas récupérer le pointeur vu qu'il y a un souci dans la DLL de CPython qui lève une exception.

n°1149151
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 13-07-2005 à 15:18:34  profilanswer
 

et la stacktrace de l'exception, elle dit quoi ?

n°1149164
theshockwa​ve
I work at a firm named Koslow
Posté le 13-07-2005 à 15:26:04  profilanswer
 

StackTrace :

Citation :

at Python.Runtime.Runtime.PyImport_ImportModule(String name)
at Python.Runtime.PythonEngine.ImportModule(String name) in d:\\XXXXXXX\\spikes\\YYYYYYYYYY_client_python\\XXXXXXXprod\\python.runtime\\pythonengine.cs:line 260
at XXXXXXX.YYDownloader.Downloader.StartDownload(String file, String saveTo) in d:\\XXXXXXX\\spikes\\YYYYYYYYYY_client_python\\XXXXXXXprod\\XXXXXXX.YYdownloader\\downloader.cs:line 68"


 
 
Edit : désolé pour l'obfuscation, mais les personnes avec qui je travaille sont assez strictes sur la confidentialité (y compris pour les noms de code des projets)
 
Edit 2 : vu qu'il y a deux sujets dans le même topic, au final, j'ai un doute sur l'exception à laquelle tu t'intéressais [:petrus75]


Message édité par theshockwave le 13-07-2005 à 15:28:54
n°1149259
theshockwa​ve
I work at a firm named Koslow
Posté le 13-07-2005 à 16:34:12  profilanswer
 

Je suis toujours preneur de remarques sur le code que j'ai posté plus haut, sinon parce que bon ... Qu'un appel de fonction passe ou non selon le type de message passé à la fonction, ca fait un peu science fiction, non ?

mood
Publicité
Posté le 13-07-2005 à 16:34:12  profilanswer
 

n°1149270
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 13-07-2005 à 16:40:49  profilanswer
 

laisse moi rentrer chez moi, je testerais ce soir :o

n°1149273
theshockwa​ve
I work at a firm named Koslow
Posté le 13-07-2005 à 16:42:54  profilanswer
 

t'es pas à la plage, ce soir ? :o
(je serai en week end, moi, en tout cas [:petrus75] )

n°1149289
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 13-07-2005 à 16:51:01  profilanswer
 

ah mais attend... tu ne testes pas si ta fenêtre reçoit WM_DEVICECHANGE apparemment ! essaie de tester la valeur de wParam, mais seulement si tu reçois un WM_DEVICECHANGE :

Code :
  1. case WM_DEVICECHANGE:
  2.    if (wParam == DBT_DEVICEARRIVAL)
  3.       showDiskDrives();
  4.    else if (wParam == DBT_DEVICEREMOVECOMPLETE)
  5.       showDiskDrives();
  6.    break;


Message édité par Harkonnen le 13-07-2005 à 16:51:33
n°1149291
theshockwa​ve
I work at a firm named Koslow
Posté le 13-07-2005 à 16:52:26  profilanswer
 

Je teste immédiatement, même si j'ai un doute, vu que l'exception est levée par une fonction qui ne s'occupe pas du message ni de sa signification, à vrai dire :/

n°1149294
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 13-07-2005 à 16:56:05  profilanswer
 

on sait jamais avec Win32 [:joce]

n°1149306
theshockwa​ve
I work at a firm named Koslow
Posté le 13-07-2005 à 17:06:26  profilanswer
 

d'un seul coup, j'ai comme un doute que ce soit un WM_DEVICECHANGED, le message en question. En effet, je ne capture plus l'évènement avec le code suivant :
 

Code :
  1. protected override void WndProc(ref Message m)
  2.  {
  3.   switch(m.LParam.ToInt32())
  4.   {
  5.    case 0x0219: // WM_DEVICECHANGE
  6.     switch(m.WParam.ToInt32())
  7.     {
  8.      case 0x8000: // New device connection (DBT_DEVICEARRIVAL)
  9.       showDiskDrives(); // raises an exception
  10.       break;
  11.      case 0x8004: // Removing a device (DBT_DEVICEREMOVECOMPLETE)
  12.       showDiskDrives(); // raises an exception
  13.       break;
  14.     }
  15.     break;
  16.    default:
  17.     if(showDiskDrivesOnNextMessage)
  18.     {
  19.      showDiskDrivesOnNextMessage = false;
  20.      showDiskDrives(); // runs as expected
  21.     }
  22.     break;
  23.   }
  24.   base.WndProc (ref m);
  25.  }


 
je vais regarder quel est le code du message qu'il sort quand j'arrive à le capturer, ca donnera peut-être une indication

n°1149307
theshockwa​ve
I work at a firm named Koslow
Posté le 13-07-2005 à 17:06:35  profilanswer
 

:heink: le LParam a pour valeur 1242332, soit 0x12F4DC, ce qui ne correspond à aucun des messages décrits dans WinUser.h :sweat:

n°1149398
theshockwa​ve
I work at a firm named Koslow
Posté le 13-07-2005 à 18:22:24  profilanswer
 

c'est pas le LParam qui a l'id du message (qui peut être à WM_DEVICECHANGE) c'est la property Msg qui donne cet identifiant ... Donc, c'est bon, c'est bien ce message là
 
 
...
 
 
on ne se moque pas :o  
 
(cependant, ca ne change absolument rien au problème)

n°1152193
theshockwa​ve
I work at a firm named Koslow
Posté le 18-07-2005 à 09:43:26  profilanswer
 

De retour sur le sujet ! [:pitouxm]

n°1152319
theshockwa​ve
I work at a firm named Koslow
Posté le 18-07-2005 à 11:12:54  profilanswer
 

pour en revenir à http://www.zope.org/Members/Brian/PythonNet, je n'arrive même pas à recompiler leur console, donc mon problème doit être en dehors du code. Pour info, j'ai exactement le même problème : lors du lancement de Py_Main, cpython tente de faire au moins un import, et le premier que j'intercepte (vu que ca remonte dans la fonction crochet dont je parlais avant) lève une exception de la même manière que dans mon programme ...
 
Je dois vraiment louper quelque chose à un endroit :/
 
Edit : j'ai un peu de mal avec la balise [ url ]
 
Edit 2 : OK, j'ai trouvé ce qui clochait ... J'ai regardé le makefile fourni et ... quelle horreur  :sweat:  Ils désassemblent la dll compilée (en IL, donc) pour changer la convention d'appel des fonctions dedans, puis réassemblage en dll et là, ca donne une dll qui fonctionne pour les besoins du programme
 
Bon ... Il ne reste plus que ce problème de comportement qui diffère suivant le message qui déclenche l'appel  :p


Message édité par theshockwave le 18-07-2005 à 11:43:10
n°1152655
theshockwa​ve
I work at a firm named Koslow
Posté le 18-07-2005 à 15:53:38  profilanswer
 

Au sujet du message précédent ... Existe-t-il un autre moyen que de préfixer ses déclarations de fonction par cpp][CallConvCdecl()][/cpp] pour obtenir cet effet ? Parce que c'est sur la convention d'appel que portent les modifications faites comme le met en valeur ce début de fichier diff :

--- Python.Runtime.il 2005-07-18 11:32:07.750000000 +0200
+++ Python.Runtime.il2 2005-07-18 11:32:45.875000000 +0200
@@ -659,6 +659,8 @@
     } // end of method ClassBase::CanSubclass
 
     .method public hidebysig static int32  
+
+ modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl)
             tp_init(native int ob,
                     native int args,
                     native int kw) cil managed
@@ -676,6 +678,8 @@
     } // end of method ClassBase::tp_init
 
     .method public hidebysig static int32  
+
+ modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl)
             tp_compare(native int ob,
                        native int other) cil managed
     {


mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C#/.NET managed

  melange de code .NET et natif

 

Sujets relatifs
Comment ajouter une class de balise P dans un code php ?[VB NET] Imprimer datagrid
Code deprecated...parser de code source
problème avec code d'un menu horizontal type sliderSpip le code source ! votre avis
Problème d'intégration de code PHP ...Code interface bouton
[Access]Etat d'une requete par le codeCalculer le nbre de ligne de code source
Plus de sujets relatifs à : melange de code .NET et natif


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR