Aller au contenu

ObjectId 64 bits


(gile)

Messages recommandés

Salut,

 

Sur les systèmes 64 bits, l'ObjectId est codé sur 64 bits, comme AutoLISP ne connait que les entiers codé sur 32 bits, une nouvelle méthode : Application.Document.Utility.GetObjectIdString (non documentée, mais la documentation ActiveX a aussi disparue...) qui retourne l'ObjectID codé sur 64bits sous forme de chaîne (entier long ou hexadécimal).

Noter que la propriété ObjectId fonctionne toujours mais ne retourne pas la même chose.

 

Utilisation :

(setq *util* (vla-get-Utility (vla-get-ActiveDocument (vlax-get-acad-object))))

 

(vla-GetObjectIdString *util* obj :vlax-true)
(vlax-invoke-method *util* 'GetObjectIdString obj :vlax-true)

retournent l'ObjectId sous forme hexadécimale, ex : "000007FFFF706540"

 

 

(vla-GetObjectIdString *util* obj :vlax-false)
(vlax-invoke-method *util* 'GetObjectIdString obj :vlax-false)

retournent l'ObjectId sous forme d'entier long, ex : "8796083610944"

 

 

(vlax-invoke *util* 'GetObjectIdString obj :vlax-true)
(vlax-invoke *util* 'GetObjectIdString obj :vlax-false)

retournent tous les deux la forme hexadécimale.

 

Il semble que la forme entier long de l'ObjectId soit requise dans certains cas comme les formules de champ objet.

 

Exemple avec une fonction qui retourne l'ObjectId de 'obj' sous forme de chaîne représentant un entier 32 ou 64 bits utilisable dans une formule de champ qui fonction quelle que soit la version d'AutoCAD (>= 2004, bien sûr) :

 

(defun gc:GetObjectIdString (obj)
 (or *util*
     (setq *util* (vla-get-Utility (vla-get-ActiveDocument (vlax-get-acad-object))))
 )
 (if  (vlax-method-applicable-p *util* 'GetObjectIdString)
   (vla-GetObjectIdString *util* obj :vlax-false)
   (itoa (vla-get-ObjectId obj))
 )
)

 

  • Upvote 1

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Salut (gile),

 

Sur une 2011 32 bits sous XP 32 bits, la méthode GetObjectIdString existe, et (vla-GetObjectIdString *util* obj :vlax-false) et (itoa (vla-get-ObjectId obj)) renvoient exactement la même chaîne.

Il faudrait voir sur les versions précédentes ce qu'il en est.

Bonne nuit ! :P

Lien vers le commentaire
Partager sur d’autres sites

Merci pour le retour,

 

donc :

- GetObjectIdString n'existe pas sur A2007 (normal il n'y a pas de versions 64 bits) mais devrait être présente sur les versions proposées en 32 ou 64 bits (à partir de 2008 je crois)

- utiliser GetObjectIdString n'est donc pas une méthode fiable pour tester la version d'AutoCAD.

(je corrige dans le message ci-dessus) mais le code de la routine gc:GetObjectIdString reste valable* : si la méthode est applicable elle retourne l'ObjectID 32 ou 64 bits sous forme de chaîne et si elle ne l'est pas elle retourne l'ObjectId 32 bits sous forme de chaîne aussi..

 

*Dans la modification que tu a faite à Pline_block (ici), la méthode utilisée pour évaluer la plateforme évalue l'architecture du système d'exploitation mais pas celle d'AutoCAD et je rappelle que même si ça ne doit pas être courant, on peut avoir une version d'AutoCAD 32 bits sur un système 64 bits (à condition que la version d'AutoCAD n'exite pas en 64 bits).

pour évaluer la plateforme d'AutoCAD :

(if (  64
 32
)

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Bonjour,

 

En effet, pour la modif sur Pline_Block j'ai utilisé tel quelle la routine de Lee Mac, mais réflexion faite sa méthode n'est pas terrible.

D'après ce que j'ai vu sur le net, avec certains processeurs (getenv "PROCESSOR_ARCHITECTURE") pourrait retourner autre chose que "X64" ou "x86" (AMD64 par ex.), donc à éviter... :exclam:

 

J'ai vu une autre façon de faire sur le net, qui est de tester la version de Windows :

(> (vl-string-search "x64" (getvar "platform")) 0).

Mais ça ne fonctionnerait pas non plus dans le cas d'une vieille version d'AutoCAD installée sur un Win 64 bits...

 

Pourrais-tu expliquer ta méthode stp ? Comment sais-tu que (strlen (vl-princ-to-string (vlax-get-acad-object))) sera > à 40 sur une version 64 bits ? :casstet:

Lien vers le commentaire
Partager sur d’autres sites

C'est une méthode trouvée sur le NET (je ne sais plus ou).

 

Elle est la conséquence de codage des ObjectId sur 64 bilts, (vlax-get-acad-object) retourne quelque chose du style :

 

# avec une version 64 bits

 

ou

 

# sur une version 32 bits

 

 

où "000000013ff67e28" est l'ObjectId de l'application AutoCAD sur 64 bits (forme hexadécimale) et "00d077b4" l'ObjectID l'équivalent sur 32 bits.

 

 

La forme hexadécimale d'un entier 64 bits aura 16 caractères quand celle d'un entier 32 bits n'en aura que 8 d'où la différence de longueur de chaîne.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

  • 4 semaines après...

Salut,

 

J'en ai trouvé d'autres : ObjectId/ObjectId32, OwnerId/OwnerId32 et ObjectIdToObject/ObjectIdToObject32.

 

D'après mes tests sur AutoCAD 2011 64 bit, dans les trois cas les deux syntaxes fonctionnent,

 

Suite à quelques recherches, il semblerait que les formes *32 ne soient nécessaires qu'en VBA sur les système 64 bits (VBA ne fonctionne qu'en 32 bits, LISP fonctionne indifféremment en 32 ou 64 bits).

 

Par contre, ces propriétés et méthodes, d'après mes essais n'existent que sur les système 64 bits, elle pourraient donc servir à évaluer la version d'AutoCAD :

 

(defun gc:IsAcad64	()
 (vlax-property-available-p
   (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-acad-object)))
   'ObjectId32
 )
)

retourne T sur un AutoCAD 64 bits, nil sur un AutoCAD 32 bits

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

  • 1 mois après...

Belle trouvaille que tu a là Gile, Bravo ! :)

 

Je serai curieux de voir cependant, la valeur retourné lorsque win32 est installé sur un processeur 64...? ou lorsque AutoCAD 2007 32bits est installé sur un processeur 64 ?

 

eh oui,...ca se peut,...il y en a plein au bureau.

mais quand même....une belle approche, je vais testé.

 

MErci. :)

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Sur les systèmes 64 bits, l'ObjectId est codé sur 64 bits, comme AutoLISP ne connait que les entiers codé sur 32 bits, une nouvelle méthode : Application.Document.Utility.GetObjectIdString (non documentée, mais la documentation ActiveX a aussi disparue...) qui retourne l'ObjectID codé sur 64bits sous forme de chaîne (entier long ou hexadécimal).

Noter que la propriété ObjectId fonctionne toujours mais ne retourne pas la même chose.

 

Utilisation :

(setq *util* (vla-get-Utility (vla-get-ActiveDocument (vlax-get-acad-object))))

 

(vla-GetObjectIdString *util* obj :vlax-true)
(vla-invoke-method *util* 'GetObjectIdString obj :vlax-true)

retournent l'ObjectId sous forme hexadécimale, ex : "000007FFFF706540"

 

 

(vla-GetObjectIdString *util* obj :vlax-false)
(vla-invoke-method *util* 'GetObjectIdString obj :vlax-false)

retournent l'ObjectId sous forme d'entier long, ex : "8796083610944"

 

 

(vla-invoke *util* 'GetObjectIdString obj :vlax-true)
(vla-invoke *util* 'GetObjectIdString obj :vlax-false)

retournent tous les deux la forme hexadécimale.

 

Il semble que la forme entier long de l'ObjectId soit requise dans certains cas comme les formules de champ objet.

 

Exemple avec une fonction qui retourne l'ObjectId de 'obj' sous forme de chaîne représentant un entier 32 ou 64 bits utilisable dans une formule de champ qui fonction quelle que soit la version d'AutoCAD (>= 2004, bien sûr) :

 

(defun gc:GetObjectIdString (obj)
 (or *util*
     (setq *util* (vla-get-Utility (vla-get-ActiveDocument (vlax-get-acad-object))))
 )
 (if  (vlax-method-applicable-p *util* 'GetObjectIdString)
   (vla-GetObjectIdString *util* obj :vlax-false)
   (itoa (vla-get-ObjectId obj))
 )
)

 

Gile,...

 

ne manque-t-il pas un X à

vla-invoke-method ??

 

ex:

 

vlax-invoke-method ?

Lien vers le commentaire
Partager sur d’autres sites

Je serai curieux de voir cependant, la valeur retourné lorsque win32 est installé sur un processeur 64...? ou lorsque AutoCAD 2007 32bits est installé sur un processeur 64 ?

 

gc:GetObjectIdString devrait fonctionner dans toutes les situations.

Pour win32, je ne peux rien affirmer, mais à priori, ceci ne concerne qu'AutoCAD.

Pour AutoCAD 2007 (pas de version 64 bits), la méthode n'existe pas, donc (vlax-method-applicable-p *util* 'GetObjectIdString) retourne nil, et pour les versions pour laquelle cette méthode existe (à partir de 2008 je suppose) si la version d'AutoCAD est 32 bits, GetObjectIdString retourne l'ObjectId 32 bits sous forme de chaîne.

 

 

ne manque-t-il pas un X à

vla-invoke-method ??

 

Effectivement, merci.

Je corrige.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

  • 7 mois après...

Bonjour

 

J'ai une fonction qui utilise vla-ObjectIDToObject et qui marche très bien sur une version 32bits.

Mais en 64bits avec vla-ObjectIDToObject32 elle ne marche pas :

 

; erreur: Erreur Automation. Aucune description n'a été entrée.

 

ObjectIDToObject32 est bien faite pour ça ou j'ai raté quelquechose ??

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Il me semble (je n'affirmerais rien, je ne fais plus trop de LISP ces temps-ci) que ObjectIDToObject32, objectId32, etc ne sont utiles qu'en VBA.

En tous cas, je n'ai eu à modifier mes LISP que pour utiliser vla-GetObjectIdString dans les expressions de champs comme monté ci-dessus.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Bon, c'est curieux.

 

La ligne qui plante est un vla-ObjectIDToObject32 sur un groupe 335 de XRecord (en fait la suite de mon exemple précédent sur les overrides), et l'id sous 64bits est -5219840 (un entier long positif sous 32bits). Je ne sais pas si c'est un entier valable ..

Lien vers le commentaire
Partager sur d’autres sites

As-tu essayé avec vla-ObjectIDToObject sur ton système 64 bits ?

 

LISP ne connais pas les entiers codés sur 64bits.

Essaye (+ 1 2147483647) tu devrais avoir -2147483648 parce que 2147483647 est la limite des entiers positifs codés sur 32 bits. Ceci explique pourquoi tu obtiens un entier négatif qui n'est pas un ObjectId valide.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Oui avec vla-ObjectIDToObject ça donne :

; erreur: une exception s'est produite: 0xC0000005 (Violation d'accès)..unwind ignorée erreur inconnue

 

En fait l'Id en question vient du code 335 d'une XRecord, passé par cette routine LM:Variants->DXF : http://www.cadtutor.net/forum/archive/index.php/t-53353.html.

Peut être que ça vient de ces routines en 64bits ?

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Pour éviter ce problème on peut utiliser AutoLISP plutôt que Visual LISP pour avoir directement le ENAME de la fenêtre. De plus j'ai toujours pensé que l'accès aux dictionnaires et xrecords est plus simple avec les liste DXF.

 

L'équivalent du code de Lee en "pur AutoLISP".

 

;; gc:GetExtDict
;; Retourne le dictionnaire d'extension de l'entité (ou nil)
;;
;; Argument : ent (ENAME)

(defun gc:GetExtDict (ent)
 (cdadr (member '(102 . "{ACAD_XDICTIONARY") (entget ent)))
)

;; gc:GetXrecData
;; Retourne la liste des données affectées au Xrecord (liste de paires pointées)
;;
;; Arguments
;; dict : ENAME du dictionnaire parent
;; key : nom du Xrecord

(defun gc:GetXrecData (dict key / xrec)
 (if (and
(setq xrec (dictsearch dict key))
(= (cdr (assoc 0 xrec)) "XRECORD")
     )
   (cdr (member (assoc 280 xrec) xrec))
 )
)

;; gc:massoc
;; Retourne la liste de toutes les entrées dont la clé correspond.
;;
;; Arguments
;; key : la clé à rechercher
;; alst : la liste d'association

(defun gc:massoc (key alst)
 (if (setq alst (member (assoc key alst) alst))
   (cons (car alst) (gc:massoc key (cdr alst)))
 )
)

;; gc:GetOverrideData
;; Retourne la liste des propriétés forcées par fenêtre pour le calque donné
;;
;; Argument
;; layer : le nom du calque
 
(defun gc:GetOverrideData (layer / xdict)
 (if
   (and
     (setq layer (tblobjname "layer" layer))
     (setq xdict (gc:GetExtDict layer))
   )
    (mapcar '(lambda (x)
	(gc:GetXrecData xdict (cdr x))
      )
     (gc:massoc 3 (entget xdict))
    )
 )
)

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Et sinon il y aurait donc un problème avec vlax-variant-value et les entiers ID sous 64bits

 

vlax-variant-value n'a rien à voir, cette fonction ne fait que traduire un variant COM en valeur LISP.

 

Le problème est que sur les système 64 bits les ObjectId sont représentés par des entiers codés sur 64 bits (entre -9.2e18 et 9.2e18) quand LISP (et VBA) ne connaissent que les entiers codés sur 32 bits (entre -2 1474 83,648 et 2 147 483 647).

L'avantage des enames c'est qu'il représentent ce nombre sous forme hexadécimale dans une chaîne.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Ok compris (également l'avantage des ename, j'ai tendance à foncer sur les vla- par fainéantise ..)

Mais au final qu'est ce que je peux en conclure, sinon que vlax-variant-value traduit "un variant COM en valeur LISP" différemment en 32 bits et en 64, et que cette différence fait que ça ne marche pas en 64 ? Sinon où est le problème dans ce cas ?

 

Pour en revenir à tes fonctions très efficaces, l'argument key de gc:massoc indique les overrides, et on pourrait faire pareil pour les layerstates ??

Lien vers le commentaire
Partager sur d’autres sites

vlax-variant-value traduit "un variant COM en valeur LISP" différemment en 32 bits et en 64 ? Sinon où est le problème dans le cas 64bits ?

Non, c'est la valeur contenue dans le variant qui est différente.

Comme dit plus haut, le problème avec les système 64 bits c'est que cette valeur dépasse les capacités des nombres entiers du LISP ou du VB(A).

 

Un variant est un type particulier, une sorte de conteneur qui peut contenir des objets de types différent. Le type réel de l'objet n'est déterminé qu'à l'exécution (on parle de liaison tardive).

 

l'argument key de gc:massoc indique les overrides, et on pourrait faire pareil pour les layerstates ?

La fonction gc:massoc fonctionne comme la fonction native assoc sur les listes d'association à ceci près que assoc retourne la première occurence trouvée dans la liste et gc:massoc retourne toutes les occurences.

Par exemple, sur la liste DXF d'une polyligne (gc:massoc 10 (entget pline)) retourne tous les sommets de la polyligne.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Oui merci (j'avais pas vu que gc:massoc est une de tes fcts de base)

 

 

 

Mais je veux dire : avec vlax-variant-value je peux récupérer un objet dans une XRecord en 32 bits alors que je ne peux pas le faire en 64 ? Ce serait curieux non ??

 

----------

 

Voilà mon exemple .. Chez moi il fonctionne en 32 bits mais pas en 64 (même avec ObjectIDToObject32 ).

 

Il faut d'abord remplacer une couleur du "0" dans une présentation puis appeler (GetColorOverrides "0")

 

 

(defun GetColorOverrides (layer / doc lays xrec data)

 (vl-load-com)

 (setq doc (vla-get-ActiveDocument (vlax-get-acad-object)))
 
 (setq lays (vla-get-Layers doc))
 (setq	layer (vla-item lays layer))
 (and (eq (vla-get-HasExtensionDictionary layer) :vlax-true)
      (setq xrec (vla-item (vla-getExtensionDictionary layer) "ADSK_XREC_LAYER_COLOR_OVR"))
      (progn
 (vla-getXRecordData xrec 'cod 'val)
 (setq data (LM:Variants->DXF cod val))
 (print (vla-ObjectIDToObject doc (cadr(assoc 335 data)))) ; <-- vla-ObjectIDToObject32 pour 64 bits
 ))
)


;;-------------------=={ Variant Value }==--------------------;;
;; ;;
;; Converts a VLA Variant into native AutoLISP data types ;;
;;------------------------------------------------------------;;
;; Author: Lee McDonnell, 2010 ;;
;; ;;
;; Copyright © 2010 by Lee McDonnell, All Rights Reserved. ;;
;; Contact: Lee Mac @ TheSwamp.org, CADTutor.net ;;
;;------------------------------------------------------------;;
;; Arguments: ;;
;; value - VLA Variant to process ;;
;;------------------------------------------------------------;;
;; Returns: Data contained within variant ;;
;;------------------------------------------------------------;;
				;
(defun LM:VariantValue (value)
 ;; © Lee Mac 2010
 (cond
   ((eq 'variant (type value))
    (LM:VariantValue (vlax-variant-value value))
   )
   ((eq 'safearray (type value))
    (mapcar 'LM:VariantValue (vlax-safearray->list value))
   )
   (value)
 )
)
;;------------------=={ Variants->DXF }==---------------------;;
;; ;;
;; Converts Type and Value Variants to a DXF List ;;
;;------------------------------------------------------------;;
;; Author: Lee McDonnell, 2010 ;;
;; ;;
;; Copyright © 2010 by Lee McDonnell, All Rights Reserved. ;;
;; Contact: Lee Mac @ TheSwamp.org, CADTutor.net ;;
;;------------------------------------------------------------;;
;; Arguments: ;;
;; typ - VLA Variant of Integer type ;;
;; val - VLA Variant of Variant type ;;
;;------------------------------------------------------------;;
;; Returns: DXF List ;;
;;------------------------------------------------------------;;
(defun LM:Variants->DXF	(typ val)
 ;; © Lee Mac 2010
 (apply 'mapcar
 (cons 'cons
       (mapcar 'LM:VariantValue (list typ val))
 )
 )
)


Lien vers le commentaire
Partager sur d’autres sites

Je dois très mal m'exprimer, parce qu'on tourne en rond.

 

Un ObjectId (ou l'équivlent LISP ename) est un identifiant attribué à tous les objets (graphiques ou non) à l'ouverture des fichiers AutoCAD dans une session.

Cet identifiant est unique dans la session : deux objets, même de dessins différents, ne peuvent pas avoir le même ObjectId, mais il n'est pas pérenne : il peut être différent pour le même objet dans deux sessions différentes.

 

Un ObjectId est représenté sous la forme d'un nombre entier codé sur 32 bits sur les systèmes 32 bits et codé sur 64 bits sur les systèmes 64 bits. Le ename utilisé en LISP est un pointeur vers cet ObjectId dans lequel la valeur de l'entier est stockée sous une forme hexadécimale (chaîne).

 

Certains langages de programmation comme AutoLISP ou VB(A) ne connaissent pas les entiers codés sur 64 bits, d'où les problèmes avec les ObjectId sur les systèmes 64 bits.

 

Quand aux fonctions 'copyrightées' de Lee Mac (par ailleurs brillant Lispeur) pour convertir les variants et safearrays de l'interface COM Automation en types AutoLISP, on doit pouvoir trouver des fonctions équivalentes datant du lendemain (ou du surlendemain) de l'apparition de Visual LISP (j'en avais moi même données ici).

Ces fonctions ne font que convertir des types de données sans en changer les valeurs sous-jacentes.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Merci pour ces nouvelles explications et pour ta patience.

 

Certains langages de programmation comme AutoLISP ou VB(A) ne connaissent pas les entiers codés sur 64 bits, d'où les problèmes avec les ObjectId sur les systèmes 64 bits.

 

Pour moi le point bloquant c'est juste le fait qu'on puisse faire quelque chose (en l'occurrence avec les variants) en 32 mais pas en 64, je croyais qu'à la base c'était une hérésie ... Donc il faut en conclure qu'en fait non, c'est possible ?

Lien vers le commentaire
Partager sur d’autres sites

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 compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant
×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer. Politique de confidentialité