Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Passage de paramètres par référence à une fonction win32com

8 réponses
Avatar
Thomas Paviot
Bonjour à tous,

Je cherche, par l'intermédiaire du module win32com, à automatiser le
traitement de quelques fichiers CAO sous CATIA V5. Plus précisément, je
souhaite retrouver les paramètres d'inertie d'une pièce, et notamment la
position de son centre de gravité.

Voici le début du script :

import win32com.client
catia_app=win32com.Dispatch('catia.application')

Jusque là aucun problème, l'application se lance et win32com me donne
accès à tous les objets COM. La fonction qui donne accès aux coordonnées
du centre de gravité a pour nom GetGravityCenter. C'est une méthode de
la classe Analyze:

mon_analyse=catia_app.ActiveDocument.Product

La documentation accompagnant CATIA V5, donne un exemple Visual Basic
d'accès à cette fonction. Je cite :

"
Dim oGravityCenterCoordinatesArray(2)
Myproduct.Analyze.GetGravityCenter oGravityCenterCoordinatesArray
"

J'ai fortement l'impression que le passage de paramètres à cette
fonction se fait par référence.
Je ne sais pas transcrire cet exemple en Python. Si je crée un paramètre
pos, par exemple un 3-tuple alors il n'est pas modifié par la ligne
suivante:

pos=(0.0,0.0,0.0)
mon_analyse.GetGravityCenter(pos)
print pos
>>(0.0,0.0,0.0)

Quelqu'un peut-il m'aider?

Thomas

8 réponses

Avatar
RONIN
J'ai peut etre une solution mais , je dois dire que je n'ai jamais aissaié

il faut passer par un fichier c.
tu utilises un fichier c entre ta dll et ton appli python

static PyObject*
ftobj_GetValue(Ftobj *fo, PyObject *ao) {
FT_STATUS s;
DWORD r;

....

return PyInt_FromLong((int)r);
}

tu def ta fonction appelante en python

static PyMethodDef ftobj_methods[] = {
{"GetValue", (PyCFunction)ftobj_GetValue, METH_VARARGS, "Gets the
number"},...
}

et tu appelles (en python), la fonction que tu as creé .


je suis désolé si je ne suis pas clair, tu devrais trouvé un example qui le
fait sur le net.

si tu réussis ca m'intesse.
Avatar
Amaury
...
"
Dim oGravityCenterCoordinatesArray(2)
Myproduct.Analyze.GetGravityCenter oGravityCenterCoordinatesArray
"

J'ai fortement l'impression que le passage de paramètres à cette
fonction se fait par référence.
Je ne sais pas transcrire cet exemple en Python. Si je crée un paramètre
pos, par exemple un 3-tuple alors il n'est pas modifié par la ligne
suivante:

pos=(0.0,0.0,0.0)
mon_analyse.GetGravityCenter(pos)
print pos
(0.0,0.0,0.0)





En python, un tuple n'est pas modifiable (en anglais: non mutable).
As-tu essayé avec une liste?

pos = [0.0, 0.0, 0.0]
mon_analyse.GetGravityCenter(pos)

--
Amaury



Avatar
Laurent Pointal
Thomas Paviot wrote:
Bonjour à tous,

Je cherche, par l'intermédiaire du module win32com, à automatiser le
traitement de quelques fichiers CAO sous CATIA V5. Plus précisément, je
souhaite retrouver les paramètres d'inertie d'une pièce, et notamment la
position de son centre de gravité.

Voici le début du script :

import win32com.client
catia_app=win32com.Dispatch('catia.application')

Jusque là aucun problème, l'application se lance et win32com me donne
accès à tous les objets COM. La fonction qui donne accès aux coordonnées
du centre de gravité a pour nom GetGravityCenter. C'est une méthode de
la classe Analyze:

mon_analyseÊtia_app.ActiveDocument.Product

La documentation accompagnant CATIA V5, donne un exemple Visual Basic
d'accès à cette fonction. Je cite :

"
Dim oGravityCenterCoordinatesArray(2)
Myproduct.Analyze.GetGravityCenter oGravityCenterCoordinatesArray
"

J'ai fortement l'impression que le passage de paramètres à cette
fonction se fait par référence.
Je ne sais pas transcrire cet exemple en Python. Si je crée un paramètre
pos, par exemple un 3-tuple alors il n'est pas modifié par la ligne
suivante:

pos=(0.0,0.0,0.0)
mon_analyse.GetGravityCenter(pos)
print pos
(0.0,0.0,0.0)



Quelqu'un peut-il m'aider?


Si cela attend une adresse (référence), tu tombes dans du bas niveau,
sauf à avoir un wrapper Python, tu ne pourras pas lui passer tel quel en
argument un objet Python genre liste ou tuple.

Si ça remplit un tableau de données identiques, tu peux utiliser un
objet array du module array (voir la méthode buffer_info() pour
récupérer l'adresse des données).

Si ça remplit une structure plus complexe, tu peux utiliser soit le
module standard struct.
Il y a des versions un peu plus sympa, voir ctypes
(http://starship.python.net/crew/theller/ctypes/) ainsi que xstruct
(http://www.sis.nl/python/xstruct/xstruct.shtml).

En googlant, je suis tombé sur un exemple d'utilisation de ctypes+DCOM
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/305273

A+, bon courage, et vu que ça intéresse au moins une autre personne,
poste ta solution, elle sera archivée dans les moteurs de recherche.

Laurent Pointal.



Avatar
Olivier

J'ai fortement l'impression que le passage de paramètres à cette
fonction se fait par référence.


Je ne l'ai jamais testé dans ton contexte, mais tu devrais pouvoir
utiliser ctypes.

Un exemple ici :

http://groups.google.fr/group/comp.lang.python/browse_frm/thread/36179c60c0df1372/f137da38c4e04bb5?lnk=st&qÊlling+DLLs+from+Python&rnum=1&hl=fr#f137da38c4e04bb5

Olivier

Avatar
Thomas Paviot
...

"
Dim oGravityCenterCoordinatesArray(2)
Myproduct.Analyze.GetGravityCenter oGravityCenterCoordinatesArray
"

J'ai fortement l'impression que le passage de paramètres à cette
fonction se fait par référence.
Je ne sais pas transcrire cet exemple en Python. Si je crée un
paramètre pos, par exemple un 3-tuple alors il n'est pas modifié par
la ligne suivante:

pos=(0.0,0.0,0.0)
mon_analyse.GetGravityCenter(pos)
print pos
(0.0,0.0,0.0)





En python, un tuple n'est pas modifiable (en anglais: non mutable).
As-tu essayé avec une liste?

pos = [0.0, 0.0, 0.0]
mon_analyse.GetGravityCenter(pos)

Que le paramètre passé à la fonction soit un tuple ou une liste ne chane

en rien le problème du passage par référence. Dans les deux cas, pos
n'est pas affecté par le passage à la moulinette de la méthode
GetGravityCenter.

Thomas




Avatar
Thomas Paviot
J'ai peut etre une solution mais , je dois dire que je n'ai jamais aissaié

il faut passer par un fichier c.
tu utilises un fichier c entre ta dll et ton appli python

static PyObject*
ftobj_GetValue(Ftobj *fo, PyObject *ao) {
FT_STATUS s;
DWORD r;

....

return PyInt_FromLong((int)r);
}

tu def ta fonction appelante en python

static PyMethodDef ftobj_methods[] = {
{"GetValue", (PyCFunction)ftobj_GetValue, METH_VARARGS, "Gets the
number"},...
}

et tu appelles (en python), la fonction que tu as creé .


je suis désolé si je ne suis pas clair, tu devrais trouvé un example qui le
fait sur le net.

si tu réussis ca m'intesse.

Malheureusement, je ne dispose pas du SDK pour CATIA V5 (appelé aussi

CAA). Je n'ai donc aucune doc ni aucun header me permettant de linker un
fichier c avec les dll CATIA V5. La seule chose dont je dispose sont les
ActiveX fournies pour l'Automation de CATIA V5. Et c'est à travers elles
que je veux utiliser Python.

Thomas

Avatar
Thomas Paviot

J'ai fortement l'impression que le passage de paramètres à cette
fonction se fait par référence.



Je ne l'ai jamais testé dans ton contexte, mais tu devrais pouvoir
utiliser ctypes.

Un exemple ici :

http://groups.google.fr/group/comp.lang.python/browse_frm/thread/36179c60c0df1372/f137da38c4e04bb5?lnk=st&qÊlling+DLLs+from+Python&rnum=1&hl=fr#f137da38c4e04bb5


Olivier

J'ai déjà essayé d'utiliser le module ctypes, et notamment le fait qu'il

est possibile d'utiliser des pointeurs C pour les passer à des fonctions
incluses dans des dll. Ceci permet, il est vrai, de faire du passage de
paramètres par référence.

Malheureusement, même si quelques exemples sont fournis avec le module
ctypes, notamment comment passer à msvcrt.printf une chaîne de
caractères (exemple assez simple à comprendre), j'ai galéré pendant des
heures pour rééditer la chose avec l'exemple ci-dessus, notamment à
cause de conflits de types que je n'ai pas été en mesure de résoudre
(l'activeX CATIA attend un tableau CATArray que je n'ai jamais pu lui
refiler avec ctypes).

L'exemple fait déjà intervenir Python, ActiveX et Visual Basic, quand je
rajoute du C là-dedans je patauge compètement.

Thomas


Avatar
Thomas Paviot
Bonjour à tous,

Je cherche, par l'intermédiaire du module win32com, à automatiser le
traitement de quelques fichiers CAO sous CATIA V5. Plus précisément, je
souhaite retrouver les paramètres d'inertie d'une pièce, et notamment la
position de son centre de gravité.

Voici le début du script :

import win32com.client
catia_app=win32com.Dispatch('catia.application')

Jusque là aucun problème, l'application se lance et win32com me donne
accès à tous les objets COM. La fonction qui donne accès aux coordonnées
du centre de gravité a pour nom GetGravityCenter. C'est une méthode de
la classe Analyze:

mon_analyseÊtia_app.ActiveDocument.Product

La documentation accompagnant CATIA V5, donne un exemple Visual Basic
d'accès à cette fonction. Je cite :

"
Dim oGravityCenterCoordinatesArray(2)
Myproduct.Analyze.GetGravityCenter oGravityCenterCoordinatesArray
"

J'ai fortement l'impression que le passage de paramètres à cette
fonction se fait par référence.
Je ne sais pas transcrire cet exemple en Python. Si je crée un paramètre
pos, par exemple un 3-tuple alors il n'est pas modifié par la ligne
suivante:

pos=(0.0,0.0,0.0)
mon_analyse.GetGravityCenter(pos)
print pos
(0.0,0.0,0.0)



Quelqu'un peut-il m'aider?

Thomas

J'ai résolu mon problème.


Le module win32com prévoit le cas où il est nécessaire d'utiliser des
fonctions qui attendent un paramètre passé par référence. On trouve un
excellent exposé du problème sur
http://www.oreilly.com/catalog/pythonwin32/chapter/ch12.html

Je reporte notamment l'explication qui est faite avec un exemple simple.

"Prenons par exemple une fonction C qui ressemblerait à:

BOOL GetSize( int *left, int *right, int *top, int *bottom);

En C, l'appel à cette fonction se ferait de la manière suivante:

int left, right, top, bottom;
BOOL ok;
ok = GetSize( &left, &right, &top, &bottom);

Avec Visual Basic, nous aurions:

Declare GetSize( ByRef left as integer, ByRef right as integer, _
ByRef top as integer, ByRef bottom as integer) as Integer
...
ok = GetSize(left, right, top, bottom);

Avec python, et après win32com.client.Dispatch:

left, right, top, bottom = GetSize()
"

win32com.client détecte donc, au moment du Dispatch, si la fonction
attend un paramètre par référence et, si tel est le cas, la fonction
renvoie un tuple avec la valeur du paramètre.


Malheureusement, ceci ne fonctionne pas avec les ActiveX CATIA V5, sans
qu'il me soit possible de savoir pourquoi. Une autre personne a déjà eu
le même problème que moi, et qui m'a soufflé une solution guère élégante
mais qui fonctionne : l'utilisation d'un proxy Visual Basic.

J'ai écrit une dll ActiveX avec Visual Basic:

Public Sub GetGravityCenter(o as Object, ByRef a() As Variant)
o.Get Inertia a
End Sub

J'ai gardé le nom par défaut Project1 et le nom de la classe par défaut
également Class1. Compilé le projet "Project1.dll". 'enregistrement de
l'ActiveX est faire automatiquement par VB. VOus pouvez néanmoins
vérifier qu'elle est bien enregsitrée avec le COM Brower de PythonWin.

Voici donc ce que devient le code pour accéder aux coordonnées du centre
d'inertie d'une pièce CATIA:

import win32com.client
proxy=win32com.client.Dispatch("Project1.Class1")
catia=win32com.client.Dispatch("CATIA.Application")

productÊtia_app.ActiveDocument.Product
pos=[0,0,0]
gravity_center=proxy.GetGravityCenter(product,pos)
print gravity_center
print pos

Et voici le résultat de la console:
(<win32com.gen_py.CATIA V5 PSInterface instance at 0x167>,(9.5,0.0,0.0)
[0,0,0]



On remarque que pos n'a toujours pâs été affectée, par contre je
récupère la position du centre de gravité que je cherche:
gravity_center[1]

Je reste preneur si quelqu'un trouve une autre solution, qui ne
nécessiterait pas la compilation d'une dll ActiveX avec Visual Basic.

Thomas