Test rhinoinside: first step with Python but

Hello
I try this to send and receive data between two components, it’s clear that the second component
responds to slider changes but the string always empty
What am I missing here?

import Rhino
import rhinoscriptsyntax as rs
import Grasshopper as gh
        
class Receiver:
        
    def __init__(self):
        self.comp = None
        self.registered = False
        self.str = ''
        
    def RunScript(self):
        self.Receive(ghenv.Component)
        self.Receive_str = self.str
        
    def Receive(self,component):
        if not self.registered:
            Rhino.Runtime.HostUtils.RegisterNamedCallback("Send_data", self.RiRhino)
            self.comp = component
            self.registered = True
                    
    def RiRhino(self, sender, args):
        if args.TryGetString("data"):
            self.str = args.TryGetString("data")[1]
        self.comp.ExpireSolution(True)
        

Receive_str = Receiver()

print Receive_str

Do share the GH definition as well so we get the complete thing to work with.

Hi @nathanletwory

This is the file

rhinoinside python.gh (6.1 KB)

Couple of points:

  • In your receiving component you never call the Receive() function. You probably should do that in the __init__. Adding self.Receive() at the end of your __init__ implementation makes sure it is called
  • You are continually instantiating a new instance of your Receiver class. You probably want to put it in scriptcontext.sticky or so and use that instance instead of newing up one all the time.
  • Using NamedCallbacks with NamedEventArgs isn’t going to make your script be Rhino Inside by itself. Rhino Inside you get when you new up Rhino.Runtime.InProcess.RhinoCore.

Anyway, this seems to work

class Receiver:
        
    def __init__(self):
        self.comp = None
        self.registered = False
        self.str = ''
        self.RunScript()
        
    def RunScript(self):
        self.Receive(ghenv.Component)
        self.Receive_str = self.str
        
    def Receive(self,component):
        if not self.registered:
            Rhino.Runtime.HostUtils.RegisterNamedCallback("Send_data", self.RiRhino)
            self.comp = component
            self.registered = True
                    
    def RiRhino(self, sender, args):
        print "running RiRhino"
        if args.TryGetString("data"):
            self.str = args.TryGetString("data")[1]
        self.comp.ExpireSolution(True)
        

if 'it' in sc.sticky:
    thing = sc.sticky['it']
else:
    thing = Receiver()
    sc.sticky['it'] = thing
    
Receive_str = thing.str

1 Like

Thank you very much @nathanletwory for explanation and the solution
I will try to make it work with Rhino inside

I don’t know why sc.sticky sometimes stop working when i use another component to send and receive data
I used the second choice by adding self.Receive() at the end of __init__ but still the same problem
the text printed in the sender component but empty in the receiver

sender_receiver.gh (4.0 KB)

You need to do both steps: call Receive and use sticky dictionary instead of newing up all the time as you do on line 26.

For fun, and learning purposes, set some random value on line 11, say a new Guid each time, or a random number. You’ll see that on each change in your definition a new number or Guid is printed. That is because you’re newing up all the time. And newing up each time the Python component is evaluated will result in all the instances never getting to get the actual data. self.str = random.random() (and of course import random at the begin of your script) should be enough for the random number.

This is the reason you need to use sticky dictionary, to ensure you always have only the one instance. Otherwise it is not going to work.

1 Like

Thanks @nathanletwory for the explanation.
I will use sdk mode and sticky for pocedural mode, and Rhino inside looks like it need c# learning so i can’t do anything with it at this time

You could also use the if “foo” not in globals() method for making persistent variables. This works similar to sticky, but with a scope that’s local to one GHPython component.

1 Like

You can use Rhino Inside CPython, but maybe you should first explain what you are trying to achieve.

Maybe Hops already does what you want. Or if you look for more custom do Rhino compute.

1 Like

Thanks @AndersDeleuran , i don’t know if both of them will work in external python editor but i will try it with two opened Rhino.

I want to connect Ansys discovery Live to Grasshopper.
Ansys already have a feature to let other softwares connect to SpaceClaim with possibility to receive and send some commands, but some commands work only inside Ansys.
And both of them use Ironpython.which make the connection easier that why i want try if their Ironpython can detect or receive value from the script above.
And i hope Rhino will have similar feature to open session from other software and use everything directly

In that case check out rhino-developer-samples/Program.cs at 7 · mcneel/rhino-developer-samples · GitHub .

Essentially set up IronPython script in Ansys such that you can import Rhino.Runtime.InProcess, then instantiate RhinoCore

1 Like

Great , thank you @nathanletwory
I convert the code to Python with SharpDevelop, i will test it later

from System import *
from System.IO import *
from System.Reflection import *
from Rhino.Runtime.InProcess import *
from Rhino.Geometry import *

class Program(object):
	def __init__():
		RhinoInside.Resolver.Initialize()

	def Main(args):
		try:
		except Exception, ex:
			Console.Error.WriteLine(ex.Message)
		finally:

	Main = staticmethod(Main)

	def MeshABrep():
		sphere = Sphere(Point3d.Origin, 12)
		brep = sphere.ToBrep()
		mp = MeshingParameters(0.5)
		mesh = Mesh.CreateFromBrep(brep, mp)
		Console.WriteLine("Mesh with {mesh[0].Vertices.Count} vertices created")

	MeshABrep = staticmethod(MeshABrep)

FWIW I would refrain from using from xyz import *, since you don’t know if different modules contain symbols that are named the same. It is nice for being lazy, but not very good practice in Python code in actually used code. You should prefer for instance import xyz, or if you think the module name becomes too long you can do import SomeVeryLong.NamedModule as xyz.

Yes that what i did, i will try because i read in an old topic that rhinoinside work only with CPython.