Notifications
Clear all

[Closed] struct own member access as optional function param issue

Hi guys, I cannot figure the reason why I’m getting an error while trying to access a structure local variable from the same structure as optional function parameter. Already found a workaround, not a big deal, but I’d like to understand what’s going on. In these simple examples the outcome is clear, but in a more complex program, error messages are bizarre to use an euphemism. Under each function call there’s the listener output.

(
    struct DummyStruct
    (
        iValue = 16,
        
        function printIt iInput:iValue =
        (
            format "the value is: %
" iInput
        )
    )
    
    -- Create structure instance
    local theDummy = DummyStruct()

    theDummy.printIt iInput:42
    -- the value is: 42

    theDummy.printIt()
    -- Error occurred in anonymous codeblock; filename: ; position: 263
    --  Frame:
    --   DummyStruct: StructDef:DummyStruct
    --   theDummy: (DummyStruct iValue:16)
    -- Runtime error: Struct member access requires instance: iValue
)

As highlighted in green, structure has been instanced before calling its method.
Simple workaround:

(
    struct DummyStruct
    (
        iValue = 16,
        
        function printIt iInput: =
        (
            if (iInput == unsupplied) do
                iInput = iValue

            format "the value is: %
" iInput
        )
    )
    
    -- Create structure instance
    local theDummy = DummyStruct()

    theDummy.printIt iInput:42
    -- the value is: 42

    theDummy.printIt()
    -- the value is: 16
)

Thank you for any elucidation.

  • Enrico
8 Replies
 JHN

Yes, aren’t structs just missing the finesses of a real object. How many times I wanted to use this->someVar on an object… I don’t have the one true answer, but it seems to me that on creating the new object you can’t assign both a variable and a “method” variable name to the same name and expect the struct to figure it out. That’s why a this/self would be sooo great.

-Johan

1 Reply
(@gravey)
Joined: 11 months ago

Posts: 0

you sort of can use a this/self reference but it’s not implicit or as robust as we would like it to be and it doesnt really help with the Enrico’s problem. here’s an example though:

struct testStruct
  (
  	this,
  	fn testFunc =
  	(
  		-- should be undefined
  		format "testValue: %
" testValue
  	),
  	fn testThisFunc =
  	(
  		-- should be 10
  		format "testValue: %
" this.testValue
  	),
  	fn CreateSelfReferencingStruct =
  	(
  		local st = testStruct()
  		st.this = st
  		return st
  	),
  	testValue = 10
  )
  test = testStruct()
  test.this = test
  test.testFunc()		-- should be undefined
  test.testThisFunc() -- should be 10

as you can see, the main advantage here is that you dont need to re-order your struct members to get them to work correctly if you use the this.<member> syntax. i’m sure there are other advantages that i can’t think of off the top of my head

Very good idea here, thank you for the tip, I’m sure it will come in handy. About the issue I found, as I said, is not a big problem as soon as we can go with the workaround. A bit annoying, for sure, but absolutely bearable. I only wish I knew why it behaves like that, because it throws so weird errors, that in complex programs could be hard to debug. It seems it points to a wrong position in memory and gets whatever is there.

  • Enrico

the reason it behaves like that is because its a parser problem – as it parses any external variables are calculated immediately (like defining default parameters for a method), then function code is evaluated later at call time, which is what allows you to access information at different times successfully.

as far as the self-referencing, one thing you’re going to run into with that if you start doing a lot with it is crazy long print loops – a struct’s printout is to print its members, and if it has a member pointing to itself, it gets stuck in a loop.

I went down this road…we’ve come up with a couple of solutions at blur, the first is building a classdef object in C++ based on python code (including inheritance as well as all standard pythonic builtins call, getitem, getattr, etc.)


 ClassA = classDef "ClassA" (
 	struct _MyClassA (
 		_variable = undefined,
 		function __init__ self value = (
 			self._variable = value
 		),
 		function printIt self value: = (
 			if ( value == unsupplied ) then value = self._variable
 			print value
 		)
 	)
 )
 
 ClassB = classDef "ClassB" (
 	struct _MyClassB (
 		function __init__ self = (
 			ClassA.__init__ self 20
 		),
 		function printIt self value: = (
 			if ( value == unsupplied ) then (
 				print "B's value is unsupplied"
 			)
 			ClassA.printIt self value:value
 		)
 	)
 ) baseClass:( ClassA )
 
 a = ClassA( 5 )
 b = ClassB()
 
 a.printIt()
 b.printIt()
 b.printIt value:4
 

You would need the blurDLX.dlx from our http://blur-dev.googlecode.com website to run that (its included in the Blur3dsMax downloads for your max-version, though we’ve depracated it)

Thats one solution. The second solution is the one we’re much more excited about.

The other that we’re pushing more internally (and seeing how much external interest it garners) is going to a pure python solution – we developed a way to just run 3dsMax as a Python module, and have a full python interpreter running in 3dsMax and get true objects from Python vs. trying to hack around maxscript.

All the code that you’d need to get started with Py3dsMax is available at the blur-dev site as well.

Hope that helps a bit!

hey Eric, I’m not sure what version of max you had that infinite print issue but i’m running 2009 and have no problems with it. if you run the code i posted above you will see the print out for the struct recognises that is is recursive and prints as such like this:
(testStruct this:<<recursive Struct:testStruct>> testValue:10)

1 Reply
(@ehulser)
Joined: 11 months ago

Posts: 0

Oh cool – looks like they’ve fixed that…as of max 9 I know that was still a problem – instead of printing the recursive thing, it’d actually keep printing…so they fixed it since then (don’t know which version)

Hi Eric,
thank you for the explanation. After I came back from a quite long journey through C++, I found my coding style completely changed, I’d dare to say a bit smarter, but often frustrating, trying to force objects knowledge in MaxScript, thus facing weird issues like this one with stucts.

As a developer I’m very excited about your work with Python in 3ds Max, and can see the potentials of the mix. From my point of view the strongest benefit is related to interface development, but I understand it’s only one among many others I cannot even figure out. As a matter of fact I check your blur-dev site for news every day. I don’t have any knowledge of Python but ever heard good things about, don’t think it should be too difficult to get after C++.

There’s only a big question (maybe trivial too) that concerns me as tool developer: distribution. I know many artists are reluctant to install anything but the script itself, I mean things like adding AVGuard dlx to 3ds Max version 9 for advanced functions in MaxScript. Sometimes they’re not even allowed. To run Python code, correct me if I’m wrong, an artist should install all the packages you published by following walk through in “Getting Started” page according to their 3ds Max version. I don’t want to put anyone down, but I hardly believe an artist would go through it and come back alive.

A more straightforward, read few clicks, installation package would be much more friendly and would help developers to convey their software. I’m sure at this stage you released everything as is, paying attention to much more substantial issues, and the whole package is directed to experienced developers, the rest will come. Thank you very much for making this true and releasing your hard work for free to public, I’ll keep following you and as soon I get the chance, join in the Python adventure.

  • Enrico

Hey Enrico –

Yeah, you are completely right – I don’t expect distribution to be really that feasable right now – we are working on an easier installation system (1 installer vs. a bunch…) but it literally just hit our boxes at the studio and recieved a lot of interest in it publically.

The ideal hope is that it generates enough interest from Autodesk that they pick it up and actually incorporate it. We already have a solution to run the same PyQt system in Softimage (and I’m sure it isn’t hard to get to run in Maya) they could use the same base coding system throughout all of their applications – then we don’t have to handle the distribution – it would just “be”.

Thats the ideal, we’ll see. In the short term, we’re working on an easier installation system and building up support.

Eric