GEGEMATIC Posté(e) le 21 septembre 2012 Posté(e) le 21 septembre 2012 Bonjour,Gile avait déjà expliqué pas mal de choses dans un sujet vieux de 2 ans, mais on ne trouve rien de bien en forme sur le Web Pour faire une petite synthèse, en VB (nul n'est parfait) Voici ce que j'ai mis dans le fichier AcadExtensions.vbIl y a des auteurs crédités, mais je ne sais pas vraiment si ils sont les seuls à avoir participé: 'Classe pour évaluation lisp dans .net 'ajoutée le 20/09/2012 'http://www.theswamp.org/index.php?topic=35714.0 'LispDataType 'None 5000 'Double 5001 'Point2d 5002 'Int16 5003 'Angle 5004 'Text 5005 'ObjectId 5006 'SelectionSet 5007 'Orientation 5008 'Point3d 5009 'Int32 5010 'Void 5014 'ListBegin 5016 'ListEnd 5017 'DottedPair 5018 'Nil 5019 'T_atom (T) 5021 'PromptStatus 'None 5000 'Modeless 5027 'Other 5028 'OK 5100 'Keyword -5005 'Cancel -5002 'Error -5001 Imports System.Runtime.InteropServices Imports Autodesk.AutoCAD.DatabaseServices Imports Autodesk.AutoCAD.EditorInput Namespace AcadExtensions ' Credits to Tony Tanzillo, Alexander Rivilis, Kerry Brown... ''' <summary> ''' Provides methods to comunicate with AutoLISP. ''' </summary> Public Class LispExtensions <System.Security.SuppressUnmanagedCodeSecurity()> _ <DllImport("acad.exe", EntryPoint:="acedInvoke", _ CharSet:=CharSet.Unicode, CallingConvention:=CallingConvention.Cdecl)> _ Private Shared Function acedInvoke(ByVal args As IntPtr, ByRef result As IntPtr) As Integer End Function ''' <summary> ''' Invoke a LISP function. ''' The LISP function must be defined as an external subroutine using the c: prefix or invoking vl-acad-defun. ''' This is no more mandatory since A2011 as the managed Application.Invoke() method wraps acedInvoke. ''' </summary> ''' <param name="args">The function name (string) following by the function arguments.</param> ''' <returns>The LISP function return value or null if failed.</returns> Public Shared Function InvokeLisp(ByVal args As ResultBuffer) As ResultBuffer Dim ip As IntPtr = IntPtr.Zero Dim status As Integer = acedInvoke(args.UnmanagedObject, ip) If status = CInt(PromptStatus.OK) AndAlso ip <> IntPtr.Zero Then Return ResultBuffer.Create(ip, True) End If Return Nothing End Function <System.Security.SuppressUnmanagedCodeSecurity()> _ <DllImport("acad.exe", EntryPoint:="acedPutSym", _ CharSet:=CharSet.Unicode, CallingConvention:=CallingConvention.Cdecl)> _ Private Shared Function acedPutSym(ByVal args As String, ByVal result As IntPtr) As Integer End Function ''' <summary> ''' Set a LISP variable value. ''' </summary> ''' <param name="name">The variable name.</param> ''' <param name="rb">The variable value</param> Public Shared Sub SetLispSym(ByVal name As String, ByVal rb As ResultBuffer) acedPutSym(name, rb.UnmanagedObject) End Sub <System.Security.SuppressUnmanagedCodeSecurity()> _ <DllImport("acad.exe", EntryPoint:="acedGetSym", _ CharSet:=CharSet.Unicode, CallingConvention:=CallingConvention.Cdecl)> _ Private Shared Function acedGetSym(ByVal args As String, ByRef result As IntPtr) As Integer End Function ''' <summary> ''' Get a LISP variable value. ''' </summary> ''' <param name="name">The variable name.</param> ''' <returns>The variable value or null if failed.</returns> Public Shared Function GetLispSym(ByVal name As String) As ResultBuffer Dim ip As IntPtr = IntPtr.Zero Dim status As Integer = acedGetSym(name, ip) If status = CInt(PromptStatus.OK) AndAlso ip <> IntPtr.Zero Then Return ResultBuffer.Create(ip, True) End If Return Nothing End Function End Class End Namespace Puis voici ce que j'ai mis dans une classe de commande autocad :Vous pourrez donc tester quelques exemples réalisés à partir des exemples de Gile. (ne vous étonnez pas des commentaires naifs de mon cru que l'on trouve dans le code: Je note bêtement tout ce que je remarque et que je ne comprends pas ...) Imports Autodesk.AutoCAD.ApplicationServices Imports Autodesk.AutoCAD.DatabaseServices Imports Autodesk.AutoCAD.EditorInput Imports Autodesk.AutoCAD.Runtime 'necessaire quand est dans un autre module : 'Imports AcadExtensions 'lorsque qu'une autre classe de commands est présente dans le projet, il faut désactiver sa compilation pour que les 'CommandMethod fonctionnent Namespace LispVbsample Public Class Commands <CommandMethod("EvalCustomLisp")> _ Public Sub EvalCustomLisp() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim ed As Editor = doc.Editor ' create a result buffer containing a LISP list Dim input As New ResultBuffer( New TypedValue(CInt(LispDataType.ListBegin)), New TypedValue(CInt(LispDataType.Int16), 12), New TypedValue(CInt(LispDataType.Text), "toto"), New TypedValue(CInt(LispDataType.T_atom)), New TypedValue(CInt(LispDataType.ListEnd))) ' bind the list to a 'lst1' LISP variable AcadExtensions.LispExtensions.SetLispSym("lst1", input) ' call the 'foo' Lisp function which binds the reversed list to 'lst2' ' (defun foo () (setq lst2 (reverse lst1))) (vl-acad-defun 'foo) AcadExtensions.LispExtensions.InvokeLisp(New ResultBuffer(New TypedValue(CInt(LispDataType.Text), "foo"))) ' get the 'lst2' variable value Dim output As ResultBuffer = AcadExtensions.LispExtensions.GetLispSym("lst2") ' print the value to the commande line For Each tv As TypedValue In output ed.WriteMessage(vbLf & "Type: {0}" & vbTab & "Value: {1}", tv.TypeCode, tv.Value) Next End Sub <CommandMethod("EvalCustomLispWithArg")> _ Public Sub EvalCustomLispWithArg() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim ed As Editor = doc.Editor ' create a result buffer containing a LISP expression containing a function call, with a single list argument Dim input As New ResultBuffer( New TypedValue(CInt(LispDataType.Text), "fooArg"), New TypedValue(CInt(LispDataType.ListBegin)), New TypedValue(CInt(LispDataType.Int16), 12), New TypedValue(CInt(LispDataType.Text), "toto"), New TypedValue(CInt(LispDataType.T_atom)), New TypedValue(CInt(LispDataType.ListEnd))) 'à ce stade, input ressemble à ça: ' "fooArg" '( 12 "toto" 'T) 'On note que les parenthèses de l'évaluation de la fonction ne sont pas nécessaires, mais celles de la liste d'arguments le sont 'si la fonction accepte plusieurs arguments, pas de parenthèses ! 'copier coller suivant dans fenetre texte autocad pour définition fooarg : ' (defun fooArg ( lst1 ) (setq lst2 (reverse lst1))) (vl-acad-defun 'fooArg) ' call the 'fooArg' Lisp function which binds the reversed list to 'lst2' AcadExtensions.LispExtensions.InvokeLisp(input) ' get the 'lst2' variable value Dim output As ResultBuffer = AcadExtensions.LispExtensions.GetLispSym("lst2") ' print the value to the commande line For Each tv As TypedValue In output ed.WriteMessage(vbLf & "Type: {0}" & vbTab & "Value: {1}", tv.TypeCode, tv.Value) Next End Sub <CommandMethod("EvalAutoLispWithArg")> _ Public Sub EvalAutoLispWithArg() ' create a result buffer containing a LISP list Dim input As New ResultBuffer( New TypedValue(CInt(LispDataType.Text), "Alert"), New TypedValue(CInt(LispDataType.Text), "toto a zéro")) 'copier coller suivant dans fenetre texte autocad pour définition commande autolisp "alert" '(vl-acad-defun 'alert) ' call the 'fooArg' Lisp function which binds the reversed list to 'lst2' AcadExtensions.LispExtensions.InvokeLisp(input) End Sub 'conclusion: on peut tout faire avec le lisp 'contrainte : définir chaque commande lisp appelée par .Net avec un vl-acad-defun (pas besoin de c:) 'même les commandes autolisp natives ont besoin de ce vl-acad-defun ! 'donc il vaut mieux bien organiser son code lisp pour grouper les intéractions avec .net End Class End Namespace ----------------------------------------------------------------------Site: https://www.g-eaux.frBlog: http://g-eaux.over-blog.com
(gile) Posté(e) le 22 septembre 2012 Posté(e) le 22 septembre 2012 Salut, Pour les version 2011 et ultérieures, il existe une méthode "gérée" (managed) qui permet d'éviter le P/Invoke de la méthode non gérée acedInvoke() : Application.Invoke() qui a pour signature : C#public static unsafe ResultBuffer Invoke(ResultBuffer args); VBPublic static unsafe Function Invoke(args As ResultBuffer) As ResultBuffer Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
GEGEMATIC Posté(e) le 24 septembre 2012 Auteur Posté(e) le 24 septembre 2012 Salut,donc pour être clair, on peut remplacer InvokeLisp par Public Shared Function InvokeLispManaged(ByVal args As ResultBuffer) As ResultBuffer Return Autodesk.AutoCAD.ApplicationServices.Application.Invoke(args) End Function et pour tester :<CommandMethod("EvalCustomLisp")> _ Public Sub EvalCustomLisp() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim ed As Editor = doc.Editor ' create a result buffer containing a LISP list Dim input As New ResultBuffer( New TypedValue(CInt(LispDataType.ListBegin)), New TypedValue(CInt(LispDataType.Int16), 12), New TypedValue(CInt(LispDataType.Text), "toto"), New TypedValue(CInt(LispDataType.T_atom)), New TypedValue(CInt(LispDataType.ListEnd))) ' bind the list to a 'lst1' LISP variable AcadExtensions.LispExtensions.SetLispSym("lst1", input) ' call the 'foo' Lisp function which binds the reversed list to 'lst2' ' (defun foo () (setq lst2 (reverse lst1))) (vl-acad-defun 'foo) AcadExtensions.LispExtensions.InvokeLisp(New ResultBuffer(New TypedValue(CInt(LispDataType.Text), "foo"))) 'suivant en managé: Dim retour As ResultBuffer retour = AcadExtensions.LispExtensions.InvokeLispManaged(New ResultBuffer(New TypedValue(CInt(LispDataType.Text), "foo"))) ' print the value to the commande line ed.WriteMessage(vbLf & "Retour fonction:") For Each tv As TypedValue In retour ed.WriteMessage(vbLf & "Type: {0}" & vbTab & "Value: {1}", tv.TypeCode, tv.Value) Next ed.WriteMessage(vbLf & "Lst2:") ' get the 'lst2' variable value Dim output As ResultBuffer = AcadExtensions.LispExtensions.GetLispSym("lst2") ' print the value to the commande line For Each tv As TypedValue In output ed.WriteMessage(vbLf & "Type: {0}" & vbTab & "Value: {1}", tv.TypeCode, tv.Value) Next End SubPar contre, dans la mesure où il n'existe pas de methode putlisp ou getlisp, je pense qu'il faudrait les implémenter à partir de Invoke(), puisqu'on peut faire un invoke de la fonction (eval (read "mysym")) ----------------------------------------------------------------------Site: https://www.g-eaux.frBlog: http://g-eaux.over-blog.com
GEGEMATIC Posté(e) le 24 septembre 2012 Auteur Posté(e) le 24 septembre 2012 Donc voila la même chose en utilisant invoke()J'ai ajouté une astuce pour s'affranchir du vl-acad-defun de tout ce que l'on va évaluer par .Net, le recours à evalDonc dans mon AcadExtension.vb 'Classe pour évaluation lisp dans .net 'ajoutée le 20/09/2012 'http://www.theswamp.org/index.php?topic=35714.0 'LispDataType 'None 5000 'Double 5001 'Point2d 5002 'Int16 5003 'Angle 5004 'Text 5005 'ObjectId 5006 'SelectionSet 5007 'Orientation 5008 'Point3d 5009 'Int32 5010 'Void 5014 'ListBegin 5016 'ListEnd 5017 'DottedPair 5018 'Nil 5019 'T_atom (T) 5021 'PromptStatus 'None 5000 'Modeless 5027 'Other 5028 'OK 5100 'Keyword -5005 'Cancel -5002 'Error -5001 Imports System.Runtime.InteropServices Imports Autodesk.AutoCAD.DatabaseServices Imports Autodesk.AutoCAD.EditorInput Imports Autodesk.AutoCAD.Runtime Namespace AcadExtensions ' Credits to Tony Tanzillo, Alexander Rivilis, Kerry Brown... ''' <summary> ''' Provides methods to comunicate with AutoLISP. ''' </summary> Public Class LispExtensions ''' <summary> ''' Invoke a LISP function using managed invoke() method. ''' The LISP function must be defined as an external subroutine using the c: prefix or invoking vl-acad-defun. ''' This is no more mandatory since A2011 as the managed Application.Invoke() method wraps acedInvoke. ''' </summary> ''' <param name="args">The function name (string) following by the function arguments.</param> ''' <returns>The LISP function return value or null if failed.</returns> Public Shared Function InvokeLispManaged(ByVal args As ResultBuffer) As ResultBuffer Return Autodesk.AutoCAD.ApplicationServices.Application.Invoke(args) End Function 'accompagner cette commande la commande lisp suivante: '(defun ManagedGetLispSym ( strSym ) (eval (read strSym)))(vl-acad-defun 'ManagedGetLispSym) 'par commodité, on peut la créer automatiquement au chargement Public Shared Function ManagedGetLispSym(ByVal name As String) As ResultBuffer Dim input As New ResultBuffer( New TypedValue(CInt(LispDataType.Text), "ManagedGetLispSym"), New TypedValue(CInt(LispDataType.Text), name)) 'à ce stade, input ressemble à ça: ' "ManagedGetLispSym" "name" Return AcadExtensions.LispExtensions.InvokeLispManaged(input) End Function 'accompagner cette commande la commande lisp suivante: '(defun ManagedPutLispSym ( strSym RsbValue) (set (read strSym) RsbValue))(vl-acad-defun 'ManagedPutLispSym) ''' <summary> ''' Set a LISP variable value using managed invoke(). ''' </summary> ''' <param name="name">The variable name.</param> ''' <param name="rb">The variable value</param> Public Shared Function ManagedPutLispSym(ByVal name As String, ByVal rb As ResultBuffer) GetEditor.WriteMessage(vbLf & "Entrée ManagedPutLispSym:") Dim input As New ResultBuffer( New TypedValue(CInt(LispDataType.Text), "ManagedPutLispSym"), New TypedValue(CInt(LispDataType.Text), name) ) 'GetEditor.WriteMessage(vbLf & "Input") 'For Each tv As TypedValue In input 'GetEditor.WriteMessage(vbLf & "Type: {0}" & vbTab & "Value: {1}", tv.TypeCode, tv.Value) 'Next 'GetEditor.WriteMessage(vbLf & "Input + rb") 'rb.UnmanagedObject For Each val As TypedValue In rb input.Add(val) Next 'à ce stade, input ressemble à ça: ' "ManagedPutLispSym" "name" rbvalue 'For Each tv As TypedValue In input 'GetEditor.WriteMessage(vbLf & "Type: {0}" & vbTab & "Value: {1}", tv.TypeCode, tv.Value) 'Next Return AcadExtensions.LispExtensions.InvokeLispManaged(input) ' print the value to the commande line End Function 'Ajoute les parenthèses à un resultBuffer représentant une liste 'utile si on veut réutiliser un retour de fonction lisp comme arguments d'une autre fonction lisp Public Shared Function AddParenthesisToresultBuffer(ByVal rb As ResultBuffer) As ResultBuffer Dim tv() As TypedValue = rb.AsArray If (1 < UBound(tv, 1)) Then If Not (tv(0).TypeCode = 5016) Then GetEditor.WriteMessage(vbLf & "Liste sans parenthèses") Dim input As New ResultBuffer( New TypedValue(CInt(LispDataType.ListBegin)) ) 'Ajoute les valeurs For Each val As TypedValue In rb input.Add(val) Next input.Add(New TypedValue(CInt(LispDataType.ListEnd))) Return input Else Return rb End If Else Return rb End If End Function End Class End Namespace Et dans mon LispSample.vb : Imports Autodesk.AutoCAD.ApplicationServices Imports Autodesk.AutoCAD.DatabaseServices Imports Autodesk.AutoCAD.EditorInput Imports Autodesk.AutoCAD.Runtime 'necessaire quand est dans un autre module : 'Imports AcadExtensions 'lorsque qu'une autre classe de commands est présente dans le projet, il faut désactiver sa compilation pour que les 'CommandMethod fonctionnent Namespace LispVbsample Public Class Commands Implements IExtensionApplication Private ObjectData As System.Data.DataTable Public Sub AddDocColEventCreated() AddHandler Application.DocumentManager.DocumentCreated, _ AddressOf InitialiseLispExtension GetEditor().WriteMessage(vbNewLine & "Initialisation des exemples lisp par evenement") End Sub Private Sub InitialiseLispExtension() GetEditor().WriteMessage(vbNewLine & "Création des routines lisp utiles à AcadExtension par evenement sur la création de document ") Dim doc As Autodesk.AutoCAD.ApplicationServices.Document doc = Application.DocumentManager.MdiActiveDocument doc.SendStringToExecute("(defun ManagedGetLispSym ( strSym ) (eval (read strSym)))(vl-acad-defun 'ManagedGetLispSym) ", False, False, False) doc.SendStringToExecute("(defun ManagedPutLispSym ( strSym RsbValue) (set (read strSym) RsbValue))(vl-acad-defun 'ManagedPutLispSym) ", False, False, False) GetEditor().WriteMessage(vbNewLine & "Routines lisp ManagedGetLispSym ManagedPutLispSym créées ") End Sub Private Sub Initialize() Implements IExtensionApplication.Initialize ' Initialize your plug-in application here 'ajout de l'evenement pour les prochanis docs AddDocColEventCreated() InitialiseLispExtension() End Sub Private Sub Terminate() Implements IExtensionApplication.Terminate ' Do plug-in application clean up here End Sub 'la seule fonction exemple qui utilise invoke() <CommandMethod("ManagedEvalCustomLisp")> _ Public Sub ManagedEvalCustomLisp() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim ed As Editor = doc.Editor Dim retour As ResultBuffer ' create a result buffer containing a LISP list Dim input As New ResultBuffer( New TypedValue(CInt(LispDataType.ListBegin)), New TypedValue(CInt(LispDataType.Int16), 12), New TypedValue(CInt(LispDataType.Text), "toto"), New TypedValue(CInt(LispDataType.T_atom)), New TypedValue(CInt(LispDataType.ListEnd))) ' bind the list to a 'lst1' LISP variable AcadExtensions.LispExtensions.ManagedPutLispSym("lst1", input) ' call the 'foo' Lisp function which binds the reversed list to 'lst2' ' (defun foo () (setq lst2 (reverse lst1))) (vl-acad-defun 'foo) 'Appel lisp en managé: retour = AcadExtensions.LispExtensions.InvokeLispManaged(New ResultBuffer(New TypedValue(CInt(LispDataType.Text), "foo"))) ' print the value to the commande line ed.WriteMessage(vbLf & "Retour fonction:") For Each tv As TypedValue In retour ed.WriteMessage(vbLf & "Type: {0}" & vbTab & "Value: {1}", tv.TypeCode, tv.Value) Next ed.WriteMessage(vbLf & "Lst2:") ' get the 'lst2' variable value Dim output As ResultBuffer = AcadExtensions.LispExtensions.ManagedGetLispSym("lst2") ' print the value to the commande line For Each tv As TypedValue In output ed.WriteMessage(vbLf & "Type: {0}" & vbTab & "Value: {1}", tv.TypeCode, tv.Value) Next ed.WriteMessage(vbLf & "Put lisp managé, création de la liste lst4 avec le retour de fonction, !lst4 pour vérification:") 'ajoute des parenthèses à retour retour = AcadExtensions.LispExtensions.AddParenthesisToresultBuffer(retour) 'version managée putLisp AcadExtensions.LispExtensions.ManagedPutLispSym("lst4", retour) End Sub End Class End Namespace A noter la création directe des deux routines lisp ManagedGetLispSym et ManagedPutLispSym, ce qui est bien pratique.Mais pour tester ManagedEvalCustomLisp, il ne faut pas oublier de définir(defun foo () (setq lst2 (reverse lst1))) (vl-acad-defun 'foo)à la ligne de commande. ----------------------------------------------------------------------Site: https://www.g-eaux.frBlog: http://g-eaux.over-blog.com
GEGEMATIC Posté(e) le 12 décembre 2012 Auteur Posté(e) le 12 décembre 2012 Salut à tous, et surtout à Krunch, car je m'aperçois que je n'avais jamais posté la version définitive :A la fin, j'ai mis des fonctions exemples qui te montrent comment évaluer directement une fonction lisp avec des arguments :EvalCustomLispWithArg elle permet d'évaluer des trucs du genre : (macommandelisp '(avec une liste) "etunechaine") exemple d'utilisation directement à la ligne de commande :Commande: EVALLISPEXPRESSIONExpression lisp à évaluer (avec les parenthèses) ?: (alert "coucou")nil Retour expression évaluée :Type: 5019 Value: Le code :dans LispToNetExtension.vb 'Classe pour évaluation lisp dans .net 'ajoutée le 20/09/2012 'http://www.theswamp.org/index.php?topic=35714.0 'LispDataType 'None 5000 'Double 5001 'Point2d 5002 'Int16 5003 'Angle 5004 'Text 5005 'ObjectId 5006 'SelectionSet 5007 'Orientation 5008 'Point3d 5009 'Int32 5010 'Void 5014 'ListBegin 5016 'ListEnd 5017 'DottedPair 5018 'Nil 5019 'T_atom (T) 5021 'PromptStatus 'None 5000 'Modeless 5027 'Other 5028 'OK 5100 'Keyword -5005 'Cancel -5002 'Error -5001 Imports System.Runtime.InteropServices Imports Autodesk.AutoCAD.DatabaseServices Imports Autodesk.AutoCAD.EditorInput Imports Autodesk.AutoCAD.Runtime Imports Autodesk.AutoCAD.ApplicationServices Namespace AcadExtensions ' Credits to Gile chanteau, Tony Tanzillo, Alexander Rivilis, Kerry Brown... ''' <summary> ''' Provides methods to comunicate with AutoLISP. ''' </summary> Public Class LispExtensions Dim ed ''' <summary> ''' Invoke a LISP function using managed invoke() method. ''' The LISP function must be defined as an external subroutine using the c: prefix or invoking vl-acad-defun. ''' Obsolète : ''' Lui préférer ManagedEvalStrLispExpression, qui est plus commed, car elle permet d'évaluer des fonctions qui ''' ne sont pas vl-acad-defun ou c: ''' </summary> ''' <param name="args">The function name (string) following by the function arguments.</param> ''' <returns>The LISP function return value or null if failed.</returns> Public Shared Function InvokeLispManaged(ByVal args As ResultBuffer) As ResultBuffer Return Autodesk.AutoCAD.ApplicationServices.Application.Invoke(args) End Function 'accompagner cette commande la commande lisp suivante: '(defun ManagedEvalStrLispExpression ( strLspExp ) (eval (read strLspExp)))(vl-acad-defun 'ManagedEvalStrLispExpression) 'par commodité, on peut la créer automatiquemen au chargement Public Shared Function ManagedEvalStrLispExpression(ByVal exp As String) As ResultBuffer Dim input As New ResultBuffer( New TypedValue(CInt(LispDataType.Text), "ManagedEvalStrLispExpression"), New TypedValue(CInt(LispDataType.Text), exp)) 'à ce stade, input ressemble à ça: ' "ManagedEvalStrLispExpression" "(myLispExpression arg1 arg2 ... argn)" Return AcadExtensions.LispExtensions.InvokeLispManaged(input) End Function 'read a lisp symbol 'accompagner cette commande la commande lisp suivante: '(defun ManagedGetLispSym ( strSym ) (eval (read strSym)))(vl-acad-defun 'ManagedGetLispSym) 'par commodité, on peut la créer automatiquemen au chargement Public Shared Function ManagedGetLispSym(ByVal name As String) As ResultBuffer Dim input As New ResultBuffer( New TypedValue(CInt(LispDataType.Text), "ManagedGetLispSym"), New TypedValue(CInt(LispDataType.Text), name)) 'à ce stade, input ressemble à ça: ' "ManagedGetLispSym" "name" Return AcadExtensions.LispExtensions.InvokeLispManaged(input) End Function 'put value to a lisp symbol 'accompagner cette commande la commande lisp suivante: '(defun ManagedPutLispSym ( strSym RsbValue) (set (read strSym) RsbValue))(vl-acad-defun 'ManagedPutLispSym) ''' <summary> ''' Set a LISP variable value using managed invoke(). ''' </summary> ''' <param name="name">The variable name.</param> ''' <param name="rb">The variable value</param> Public Shared Function ManagedPutLispSym(ByVal name As String, ByVal rb As ResultBuffer) GetEditor.WriteMessage(vbLf & "Entrée ManagedPutLispSym:") Dim input As New ResultBuffer( New TypedValue(CInt(LispDataType.Text), "ManagedPutLispSym"), New TypedValue(CInt(LispDataType.Text), name) ) 'GetEditor.WriteMessage(vbLf & "Input") 'For Each tv As TypedValue In input 'GetEditor.WriteMessage(vbLf & "Type: {0}" & vbTab & "Value: {1}", tv.TypeCode, tv.Value) 'Next 'GetEditor.WriteMessage(vbLf & "Input + rb") 'rb.UnmanagedObject For Each val As TypedValue In rb input.Add(val) Next 'à ce stade, input ressemble à ça: ' "ManagedPutLispSym" "name" rbvalue 'For Each tv As TypedValue In input 'GetEditor.WriteMessage(vbLf & "Type: {0}" & vbTab & "Value: {1}", tv.TypeCode, tv.Value) 'Next Return AcadExtensions.LispExtensions.InvokeLispManaged(input) ' print the value to the commande line End Function 'Ajoute les parenthèses à un resultBuffer représentant une liste 'utile si on veut réutiliser un retour de fonction lisp comme arguments d'une autre fonction lisp Public Shared Function AddParenthesisToresultBuffer(ByVal rb As ResultBuffer) As ResultBuffer Dim tv() As TypedValue = rb.AsArray If (1 < UBound(tv, 1)) Then If Not (tv(0).TypeCode = 5016) Then GetEditor.WriteMessage(vbLf & "Liste sans parenthèses") Dim input As New ResultBuffer( New TypedValue(CInt(LispDataType.ListBegin)) ) 'Ajoute les valeurs For Each val As TypedValue In rb input.Add(val) Next input.Add(New TypedValue(CInt(LispDataType.ListEnd))) Return input Else Return rb End If Else Return rb End If End Function End Class End Namespace dans myPlugin.vb Imports System Imports Autodesk.AutoCAD.Runtime Imports Autodesk.AutoCAD.ApplicationServices Imports Autodesk.AutoCAD.DatabaseServices Imports Autodesk.AutoCAD.Geometry Imports Autodesk.AutoCAD.EditorInput ' This line is not mandatory, but improves loading performances <Assembly: ExtensionApplication(GetType(AutoCAD_VB_plug_in___lisp1.MyPlugin))> Namespace AutoCAD_VB_plug_in___lisp1 ' This class is instantiated by AutoCAD once and kept alive for the ' duration of the session. If you don't do any one time initialization ' then you should remove this class. Public Class MyPlugin Implements IExtensionApplication Public Sub AddDocColEventCreated() AddHandler Application.DocumentManager.DocumentCreated, _ AddressOf InitialiseLispExtension GetEditor().WriteMessage(vbNewLine & "Initialisation des exemples lisp par evenement") End Sub Private Sub InitialiseLispExtension() 'Si plusieurs dll chargées contiennent la classe AcadExtension, chacune recréera ces fonctions lisp: 'Car pour l'instant, il n'est pas possible de tester l'existance de ces commandes tant qu'elles n'existent pas ! 'sauf en utilisant la comamnde non managée GetLispSym, mais ce n'est pas le but. GetEditor().WriteMessage(vbNewLine & "Création des routines lisp utiles à AcadExtension par evenement sur la création de document ") Dim doc As Autodesk.AutoCAD.ApplicationServices.Document doc = Application.DocumentManager.MdiActiveDocument 'fonction lisp pour évaluer un symbole lisp, passé sous forme de chaine de carractère, ex : "myvar" 'est utilisée par la Shared Function ManagedGetLispSym doc.SendStringToExecute("(defun ManagedGetLispSym ( strSym ) (eval (read strSym)))(vl-acad-defun 'ManagedGetLispSym) ", False, False, False) 'fonction lisp pour évaluer une expression lisp, passé sous forme de chaine de carractère,avec les parenthèses ex : "(ManagedGetLispSym \"myvar\")" 'en réalité, est complètement identique à ManagedGetLispSym, mais permet d'éviter la confusion entre l'évalusatio nd'un symbole et d'une expression 'est utilisée par la Shared Function ManagedEvalStrLispExpression doc.SendStringToExecute("(defun ManagedEvalStrLispExpression ( strLspExp ) (eval (read strLspExp)))(vl-acad-defun 'ManagedEvalStrLispExpression) ", False, False, False) 'fonction lisp pour affecter une valeur à un symbole lisp passé sous forme de chaine de carractère et d'un resultbuffer, ex : ManagedPutLispSym "myvar" MyRsbvalue 'est utilisée par la Shared Function ManagedPutLispSym doc.SendStringToExecute("(defun ManagedPutLispSym ( strSym RsbValue) (set (read strSym) RsbValue))(vl-acad-defun 'ManagedPutLispSym) ", False, False, False) GetEditor().WriteMessage(vbNewLine & "Routines lisp ManagedEvalStrLispExpression, ManagedGetLispSym, ManagedPutLispSym créées ") End Sub Public Sub Initialize() Implements IExtensionApplication.Initialize ' Add one time initialization here ' One common scenario is to setup a callback function here that ' unmanaged code can call. ' To do this: ' 1. Export a function from unmanaged code that takes a function ' pointer and stores the passed in value in a global variable. ' 2. Call this exported function in this function passing delegate. ' 3. When unmanaged code needs the services of this managed module ' you simply call acrxLoadApp() and by the time acrxLoadApp ' returns global function pointer is initialized to point to ' the C# delegate. ' For more info see: ' http:'msdn2.microsoft.com/en-US/library/5zwkzwf4(VS.80).aspx ' http:'msdn2.microsoft.com/en-us/library/44ey4b32(VS.80).aspx ' http:'msdn2.microsoft.com/en-US/library/7esfatk4.aspx ' as well as some of the existing AutoCAD managed apps. ' Initialize your plug-in application here 'ajout de l'evenement pour les prochains docs AddDocColEventCreated() InitialiseLispExtension() End Sub Public Sub Terminate() Implements IExtensionApplication.Terminate ' Do plug-in application clean up here End Sub 'GetEditor est utile pour afficher des messages Public Shared Function GetEditor() As Autodesk.AutoCAD.EditorInput.Editor GetEditor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor End Function 'fonction exemple qui utilise invoke() <CommandMethod("ManagedEvalCustomLisp")> _ Public Sub ManagedEvalCustomLisp() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim ed As Editor = doc.Editor Dim retour As ResultBuffer ' create a result buffer containing a LISP list Dim input As New ResultBuffer( New TypedValue(CInt(LispDataType.ListBegin)), New TypedValue(CInt(LispDataType.Int16), 12), New TypedValue(CInt(LispDataType.Text), "toto"), New TypedValue(CInt(LispDataType.T_atom)), New TypedValue(CInt(LispDataType.ListEnd))) ' bind the list to a 'lst1' LISP variable AcadExtensions.LispExtensions.ManagedPutLispSym("lst1", input) ' call the 'foo' Lisp function which binds the reversed list to 'lst2' ' (defun foo () (setq lst2 (reverse lst1))) (vl-acad-defun 'foo) 'Appel lisp en managé: retour = AcadExtensions.LispExtensions.InvokeLispManaged(New ResultBuffer(New TypedValue(CInt(LispDataType.Text), "foo"))) ' print the value to the commande line ed.WriteMessage(vbLf & "Retour fonction:") For Each tv As TypedValue In retour ed.WriteMessage(vbLf & "Type: {0}" & vbTab & "Value: {1}", tv.TypeCode, tv.Value) Next ed.WriteMessage(vbLf & "Lst2:") ' get the 'lst2' variable value Dim output As ResultBuffer = AcadExtensions.LispExtensions.ManagedGetLispSym("lst2") ' print the value to the commande line For Each tv As TypedValue In output ed.WriteMessage(vbLf & "Type: {0}" & vbTab & "Value: {1}", tv.TypeCode, tv.Value) Next ed.WriteMessage(vbLf & "Put lisp managé, création de la liste lst4 avec le retour de fonction, !lst4 pour vérification:") 'ajoute des parenthèses à retour retour = AcadExtensions.LispExtensions.AddParenthesisToresultBuffer(retour) 'version managée putLisp AcadExtensions.LispExtensions.ManagedPutLispSym("lst4", retour) End Sub 'fonction exemple qui utilise invoke(), l'expression lisp est directement entrée à la ligne de commande Autocad 'exemple : evaluer "(Prompt \"\nCoucou\")" <CommandMethod("EvalLispExpression")> _ Public Sub EvalLispExpression() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim ed As Editor = doc.Editor Dim retour As ResultBuffer Dim strEval As String = ed.GetString("Expression lisp à évaluer (avec les parenthèses) ?").StringResult 'Appel lisp en managé: retour = AcadExtensions.LispExtensions.ManagedEvalStrLispExpression(strEval) ' print the value to the commande line ed.WriteMessage(vbLf & "Retour expression évaluée :") For Each tv As TypedValue In retour ed.WriteMessage(vbLf & "Type: {0}" & vbTab & "Value: {1}", tv.TypeCode, tv.Value) Next End Sub 'fonction exemple qui utilise invoke(), le nom de la variable lisp est directement entrée à la ligne de commande Autocad 'exemple : evaluer "myVar" <CommandMethod("EvalLispSymbole")> _ Public Sub EvalLispSymbole() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim ed As Editor = doc.Editor Dim strEval As String = ed.GetString("Nom de la variable lisp à évaluer ?").StringResult ed.WriteMessage(vbLf & "ManagedGetLispSym " & strEval & " :") ' get the 'lst2' variable value Dim output As ResultBuffer = AcadExtensions.LispExtensions.ManagedGetLispSym(strEval) ' print the value to the commande line ed.WriteMessage(vbLf & "Value of the lisp symbol '" & strEval & " as resultBuffer :") For Each tv As TypedValue In output ed.WriteMessage(vbLf & "Type: {0}" & vbTab & "Value: {1}", tv.TypeCode, tv.Value) Next ed.WriteMessage(vbLf & "Put lisp managé, création de la liste lst avec le retour d'évaluation , !lst pour vérification que lst = " & strEval & " :") 'ajoute des parenthèses à retour output = AcadExtensions.LispExtensions.AddParenthesisToresultBuffer(output) 'version managée putLisp AcadExtensions.LispExtensions.ManagedPutLispSym("lst", output) End Sub 'Exemples suivants, évaluation lisp en code non managé aced (obsolete) <CommandMethod("EvalCustomLisp")> _ Public Sub EvalCustomLisp() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim ed As Editor = doc.Editor ' create a result buffer containing a LISP list Dim input As New ResultBuffer( New TypedValue(CInt(LispDataType.ListBegin)), New TypedValue(CInt(LispDataType.Int16), 12), New TypedValue(CInt(LispDataType.Text), "toto"), New TypedValue(CInt(LispDataType.T_atom)), New TypedValue(CInt(LispDataType.ListEnd))) ' bind the list to a 'lst1' LISP variable AcadExtensions.LispExtensions.SetLispSym("lst1", input) ' call the 'foo' Lisp function which binds the reversed list to 'lst2' ' (defun foo () (setq lst2 (reverse lst1))) (vl-acad-defun 'foo) AcadExtensions.LispExtensions.InvokeLisp(New ResultBuffer(New TypedValue(CInt(LispDataType.Text), "foo"))) ed.WriteMessage(vbLf & "Lst2:") ' get the 'lst2' variable value Dim output As ResultBuffer = AcadExtensions.LispExtensions.GetLispSym("lst2") ' print the value to the commande line For Each tv As TypedValue In output ed.WriteMessage(vbLf & "Type: {0}" & vbTab & "Value: {1}", tv.TypeCode, tv.Value) Next End Sub <CommandMethod("EvalCustomLispWithArg")> _ Public Sub EvalCustomLispWithArg() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim ed As Editor = doc.Editor ' create a result buffer containing a LISP expression containing a function call, with a single list argument Dim input As New ResultBuffer( New TypedValue(CInt(LispDataType.Text), "fooArg"), New TypedValue(CInt(LispDataType.ListBegin)), New TypedValue(CInt(LispDataType.Int16), 12), New TypedValue(CInt(LispDataType.Text), "toto"), New TypedValue(CInt(LispDataType.T_atom)), New TypedValue(CInt(LispDataType.ListEnd))) 'à ce stade, input ressemble à ça: ' "fooArg" '( 12 "toto" 'T) 'On note que les parenthèses de l'évaluation de la fonction ne sont pas nécessaires, mais celles de la liste d'arguments le sont 'si la fonction accepte plusieurs arguments, pas de parenthèses ! 'copier coller suivant dans fenetre texte autocad pour définition fooarg : ' (defun fooArg ( lst1 ) (setq lst2 (reverse lst1))) (vl-acad-defun 'fooArg) ' call the 'fooArg' Lisp function which binds the reversed list to 'lst2' AcadExtensions.LispExtensions.InvokeLisp(input) ' get the 'lst2' variable value Dim output As ResultBuffer = AcadExtensions.LispExtensions.GetLispSym("lst2") ' print the value to the commande line For Each tv As TypedValue In output ed.WriteMessage(vbLf & "Type: {0}" & vbTab & "Value: {1}", tv.TypeCode, tv.Value) Next End Sub <CommandMethod("EvalAutoLispWithArg")> _ Public Sub EvalAutoLispWithArg() ' create a result buffer containing a LISP list Dim input As New ResultBuffer( New TypedValue(CInt(LispDataType.Text), "Alert"), New TypedValue(CInt(LispDataType.Text), "toto a zéro")) 'copier coller suivant dans fenetre texte autocad pour définition commande autolisp "alert" '(vl-acad-defun 'alert) ' call the 'fooArg' Lisp function which binds the reversed list to 'lst2' AcadExtensions.LispExtensions.InvokeLisp(input) End Sub 'conclusion: on peut tout faire avec le lisp, et on a plus besoin de 'définir chaque commande lisp appelée par .Net avec un vl-acad-defun ni besoin de c: End Class End Namespace ----------------------------------------------------------------------Site: https://www.g-eaux.frBlog: http://g-eaux.over-blog.com
krunch Posté(e) le 13 décembre 2012 Posté(e) le 13 décembre 2012 Ok merci bien Je suis resté sur la version de gile postée ailleurs qui a l'avantage de rester en C# (pour moi c'est déjà suffisamment compliqué comme ça ..) et que je remets ci dessous.Sur mon 2010 ça marche, à la réserve près qu'un appel de c:function provoque une erreur fatale, je dois utiliser le vl-acad-defun. J'ai vu que ta méthode permets d'éviter le vl-acad-defun, mais sinon pas d'inconvénient a priori ? using System; using System.Runtime.InteropServices; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Runtime; namespace InvokeLispSample { public class Class1 { [system.Security.SuppressUnmanagedCodeSecurity] [DllImport("acad.exe", EntryPoint = "acedInvoke", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] extern static private int acedInvoke(IntPtr args, out IntPtr result); /// Invoke a LISP function. /// The LISP function must be defined as an external subroutine using the c: prefix or invoking vl-acad-defun. /// This is no more mandatory since A2011 as the managed Application.Invoke() method wraps acedInvoke. public static ResultBuffer InvokeLisp(ResultBuffer args) { IntPtr ip = IntPtr.Zero; int status = acedInvoke(args.UnmanagedObject, out ip); if (status == (int)PromptStatus.OK && ip != IntPtr.Zero) return ResultBuffer.Create(ip, true); return null; } // Test avec : // (defun foo (l) (mapcar 'strcase l)) // (vl-acad-defun 'foo) [CommandMethod("Test")] public void Test() { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; // Argument pour InvokeLisp ResultBuffer resbuf = new ResultBuffer(); // Nom de la fonction LISP : foo resbuf.Add(new TypedValue((int)LispDataType.Text, "foo")); // Argument de la fonction LISP : ("test" "invoke" "lisp") resbuf.Add(new TypedValue((int)LispDataType.ListBegin)); resbuf.Add(new TypedValue((int)LispDataType.Text, "test")); resbuf.Add(new TypedValue((int)LispDataType.Text, "invoke")); resbuf.Add(new TypedValue((int)LispDataType.Text, "lisp")); resbuf.Add(new TypedValue((int)LispDataType.ListEnd)); // Résultat de l'évaluation de (foo '("test" "invoke" "lisp")) ResultBuffer result = InvokeLisp(resbuf); foreach (TypedValue tv in result) { ed.WriteMessage(tv.Value + " "); } } } }
GEGEMATIC Posté(e) le 13 décembre 2012 Auteur Posté(e) le 13 décembre 2012 Non non, ton truc marche je pense.Mais à l'usage, le vl-acad-defun est très contraignant, car il t'oblige à n'utiliser que des commandes lisp sans arguments.Ce n'est pas la majorité de mes routines.Ce qui m'interresse dans la liaison net / lisp, c'est de pouvoir utiliser l'interface net avec des fonctions lisp.Avec le vl-acad-defun, ce n'étais pas possible pour moi.Bon courage,Gégé ----------------------------------------------------------------------Site: https://www.g-eaux.frBlog: http://g-eaux.over-blog.com
(gile) Posté(e) le 13 décembre 2012 Posté(e) le 13 décembre 2012 Mais à l'usage, le vl-acad-defun est très contraignant, car il t'oblige à n'utiliser que des commandes lisp sans arguments. Pas du tout, dans l'exemple donné par krunch, on appelle la fonction foo définie comme telle :(defun foo (l) (mapcar 'strcase l)) (vl-acad-defun 'foo) Cette fonction requiert bien un argument : une liste de chaînes, et retourne une autre liste de chaines. Elle est appelée depuis la commande .NET "Test" avec l'argument requis. Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
GEGEMATIC Posté(e) le 13 décembre 2012 Auteur Posté(e) le 13 décembre 2012 salut,Autant pour moi, ça date de septembre, je ne me rappelais plus de cette histoire de vl-acad-defun, pourtant j'avais fait des tests avec le même système ... Maintenant, je pense quand même que :retour = AcadExtensions.LispExtensions.ManagedEvalStrLispExpression("(alert "\"ça marche\")")c'est vraiment ce qu'il y a de plus simple pour faire communiquer lisp et .netet je n'ai pas à me soucier de faire un vl-acad-defun pour les milliers de routines dont je dispose. Par contre, je n'ai à peine eu le temps de m'en servir, c'est dommage. ----------------------------------------------------------------------Site: https://www.g-eaux.frBlog: http://g-eaux.over-blog.com
Messages recommandés
Créer un compte ou se connecter pour commenter
Vous devez être membre afin de pouvoir déposer un commentaire
Créer un compte
Créez un compte sur notre communauté. C’est facile !
Créer un nouveau compteSe connecter
Vous avez déjà un compte ? Connectez-vous ici.
Connectez-vous maintenant