PYTHON NODE SCRIPT (II)

 


Continuando con la entrada anterior, en esta entrada se trata de ampliar las posibilidades del nodo Python Script de Dynamo integrando un ensamblado de .NET, concretamente una biblioteca de vínculos dinámicos (.dll). De las distintas posibilidades que ofrece .NET emplearé C# si bien podría utilizarse cualquiera de los otros lenguajes disponibles como por ejemplo Visual Basic.

CREAR ENSAMBLADO (DLL)

Lo primero sería crear un ensamblado para posteriormente integrarlo en el nodo Python Script de Dynamo. Para ello utilizaremos el entorno de desarrollo (IDE) Visual Studio - en mi caso la versión 2019.

Lo primero será crear un proyecto C# denominado 'Biblioteca de clases (.NET framework)'.


Una vez creado el proyecto escribiremos el siguiente código - muy sencillito - en C#.


A continuación compilamos el proyecto para obtener un archivo denominado Test.dll

INTEGRAR Test.dll CON EL NODO PYTHON SCRIPT

La idea es hacer el ejemplo de la primera entrega pero esta vez mediante el ensamblado en C# anterior que integraremos en el nodo de Python.


Gráficamente, consiste en un nodo Code Block que define una lista con los números que vamos a sumar y que constituirá la entrada IN del nodo Python Script. Concretamente, IN[0] = [1,2,3,4,5]. Por otro lado conectamos la salida OUT a un nodo Watch para ver el resultado.

El código del nodo Python Script es el siguiente.


Veamos que hace nuestro programa.
  • CLR es el paquete necesario para poder realizar la integración de .NET con Python. Su nombre CLR - Common Language Runtime - hace referencia al entorno de ejecución de la plataforma de Microsoft .NET.
  • La referencia al ensamblado se realiza mediante el método AddReference cuyo argumento es el nombre del ensamblaje sin su extensión (dll) - en nuestro caso 'Test'. Pero, ¿dónde lo busca? La respuesta es sencilla, en la barra de menú Dynamo >> Preferencias >> Package Manager podemos añadir rutas de búsqueda para nuestros ensamblados.
            Por cierto, las sentencias del código por defecto del nodo Python Script:

                            clr.AddReference('AcMgd')
                            clr.AddReference('AcCoreMgd')
                            clr.AddReference('AcDbMgd')
                            clr.AddReference('AecBaseMgd')
                            clr.AddReference('AecProDataMgd')
                            clr.AddReference('AeccDbMgd')

        lo que hace es cargar los ensamblados que contiene la API de Autocad y Autodesk Civil3d.
  • Una vez que hemos agregado la referencia será necesario importar aquellos paquetes necesarios para resolver nuestro problema. En nuestro caso hemos cargado todas las clases de 'Test' que en esta ocasión hace referencia al espacio de nombres - aquí namespace Test - en el ensamblado que deseamos cargar.
  • Finalmente utilizamos los objetos y métodos ya declarados en el ensamblado pero en esta ocasión  desde Python. Sería la sentencia suma = obj.Suma(data[0]). En este caso utiliza el método 'Suma' del objeto 'obj' ya creado y lo asigna a la variable 'suma'
LLegado a este punto, es necesario preguntar  ¿Os ha funcionado?

Si utilizáis las versiones más recientes de Python y habéis tenido el cuidado de seleccionar como motor (también se dice 'implementación') de Python, CPython, supongo que si funcionó.
Si por el contrario, habéis utilizado una versión de Dynamo anterior o bien habéis dejado el motor por defecto, IronPython2 os debe haber salido un mensaje de error del tipo TypeError. Expected List<Single>, got List<float>

Este error indica que la dista a suministrar al método suma esta compuesto por elementos del tipo 'Single' mientras que nosotros le hemos pasado elementos del tipo 'float'.

Posiblemente haya otras soluciones pero la que yo planteo consiste en pasar todos los elementos de la lista de entrada del tipo float al tipo Single. El programa quedaría como sigue:

import sys
import clr
import System

clr.AddReference('Test')
clr.AddReference('System.Collection')

from Test import *
form System.Collections.Generic import *
from System import Single

data = IN

s_lista = List[System.Single]()

for item in data[0]:
    s_lista.Add(item)

obj = Operaciones()

suma = obj.Suma(s_lista)

OUT = suma


Esto debería funcionar !!! Por favor, si alguien encuentra otra forma de hacerlo que me lo diga.

RESUMEN

A modo de resumen podemos decir lo siguiente:
  • Python Script nos permite integrar ensamblados de .NET  mediante la biblioteca clr y el método AddReference
  • La implementación CPython realiza el cambio de tipos de manera automática para nosotros mientras que IronPython2 requiere que lo hagamos nosotros. 
Alguien puede preguntar ¿para que sirve ésto?. Aunque este ejemplo es muy simple, mediante estas bibliotecas podemos conseguir al menos dos cosas:
  • Aumentar hasta el infinito y más allá nuestras posibilidades al poder integrar a través de una dll inicial cualquier biblioteca escrita para .NET, incluso código escrito en otro lenguaje como C/C++. Quizás todo esto sea innecesario pero la puerta está abierta.
  • Ocultar nuestro código a miradas indiscretas encapsulándolo en una biblioteca (.dll)

Un ejercicio interesante que os propongo es que importéis directamente la librería que habéis creado (Test.dll) directamente desde la barra de menú Archivo >> Importar biblioteca... 

Lo comentamos en una próxima entrega...

Entradas populares