VEX structs & arrays of structs, lack of documentation

   3710   3   1
User Avatar
Member
1 posts
Joined: April 2018
Offline
I scoured the official docs, this forum and the web for any more detailed documentation about VEX structs and arrays of those, but to no avail. So I have the following questions and hope that any answers given here could maybe helpfully be added to the VEX docs (which I generally find severely incomplete & limiting, causing hours of frustrated online searches):

1. Through trial & error I found out that structs cannot be defined in the wrangle editor itself, but need to be in an external file. What are the reasons?

2. Does VEX support nested structs at all? I.e. the type of a struct field is another struct type. This doesn't seem to compile:

// defined in an external source file

struct VG_MSTEdge {
  int a;
  int b;
  float cost;
}

struct VG_MST {
  VG_MSTEdge edges[];
  int result[];
  int maxID;
}

Produces these confusing error messages:

No matching function for VG_MST VG_MST(vector; int; int). Candidates are: VG_MST VG_MST(VG_MSTEdge; int; int) (7,1:13)
Not all code paths in the function ‘VG_MST’ return a value.

3. The following function computes the minimum spanning tree from a set of edges. Why does this produce an illegal indexing error in the highlighted line? Is there an error with the function parameters? What is the correct way to pass an array of structs?

Compiler error: "Call to undefined array index operator 'VG_MSTEdge VG_MSTEdge'"

struct VG_MSTEdge {
  int a;
  int b;
  float cost;
}

int vg_mst(const VG_MSTEdge edges[]; int maxID; int mst[]) {
    VG_DisjointSet g;
    g->init(maxID + 1);

    float costs[] = {};

    for(int i = len(edges); --i >= 0 {
        VG_MSTEdge e = edges[i]; /// <---- error, why?
        append(costs, e.cost);
    }
    int order[] = argsort(costs);

    foreach(int i; order) {
        VG_MSTEdge e = edges[i];
        if (!g->unified(e.a, e.b)) {
            g->union(e.a, e.b);
            append(mst, i);
        }
    }
    return len(mst);
}

4. Are the following forms of array declaration all equivalent? If so, why have that many syntax options? If not, what are the differences?

int[] foo = array();
int[] foo = {};
int foo[] = array();
int foo[] = {};

I'm really grateful for any answers to these questions! But as mentioned elsewhere, I also find it sad that after all this time and VEX being one of most powerful and exciting features of Houdini, it's been consistently one of the least documented aspects and is doing the whole VEX coding experience a huge disservice and causing ongoing unnecessary frustration…

As a maintainer of several large open source projects, I know from own experience that documentation always is one of the main pain points of a project, both for novice and experienced users. OTOH, Houdini costs serious $$$ and had a few decades to improve… so my hope for every new version update is a little more investment into docs rather than more features.

Thanks in advance!
User Avatar
Staff
2591 posts
Joined: July 2005
Offline
1) Wrangles are a bit of a strange beast. The wrangle code is actually pre-processed and used to generate a nested function which is called. I think we should try to fix the process so that structs could be declared in the nested function. It's likely a short-coming in the compiler.

If you dive into the wrangle, you should be able to view the generated raw VEX code on the enclosed node.

2) If you provide a default initializer for the edges array, it seems to be more acceptable
struct VG_MST {
VG_MSTEdge edges[] = {};
int _result[];
int maxID;
};
The compiler should probably not require that initializer though.

2b) I found a bug in the compiler than complains about the result declaration. It should be fixed in an upcoming build.

3) I wasn't able to reproduce your error (I assume the emoticon was a semicolon ; followed by a close brace )

4) The following is valid C++ too
    const int foo[] = { 1, 2, 3 };
int const foo[] = { 1, 2, 3 };
const int *foo = function();
But yeah, VEX is a bit loose with declarations.
User Avatar
Member
2 posts
Joined: June 2017
Offline
@mark
Is there a problem with arrays and custom structs? I just burned a day figuring out the bug mentioned above but I'm still seeing data corruption in vex when I copy a side a structure with array member. The member array does not seem to be copied.

struct StructOfArray {
  float _InternalValues[] = {};
  int _SomeOtherFieldValue;
}

function void TestFunction()
{
    StructOfArray arrayOfStructs[];

    for(int i=0; i<10;i++) {
        StructOfArray newElem;
        newElem._InternalValues = {1,2,3};
        newElem._SomeOtherFieldValue = i;
        arrayOfStructs[i] = newElem;
    }

    for(int i=0; i<10;i++) {
        printf("Struct %g: {\n  InternalValues: %g,\n  _SomeOtherFieldValue: %g\n}\n", i, 
            arrayOfStructs[i]._InternalValues, arrayOfStructs[i]._SomeOtherFieldValue);
    }
}



On a separate note, I'd agree with @toxi and would like to add some more feedback re:documentation.

Most of my frustration is wrestling with programming-101 level things bc lack of documentation which becomes a major deterrent from adopting Houdini fully as a studio. I understand the target audience has not been traditionally developers/highly technical tech directors but might be something to consider as houdini adoption expands out. It's ironic bc imho, the robustness of Houdini from a software engineering perspective is almost unrivaled.

For example, today I spent 2 hours getting a multiple scattering volumetric baker running and working in & out of unreal and our pipeline thanks to the tight HoudiniEngine integration. Then I spent 8 hours trying to figure out how to resize arrays bc lack of documentation (vex ownership semantics aren't well documented and/or incorrect from observed behavior, vcc pragma parsing seems C like but not really, HDK documentation is lacking as I also attempted to just write a C++ plugin, etc).
Edited by ikrima - May 1, 2019 07:27:08
User Avatar
Staff
2591 posts
Joined: July 2005
Offline
VEX doesn't allow arrays of arrays. Even if you try to hide it in a struct.
However, the compiler should probably warn you that this is invalid code. I'll submit a bug.
  • Quick Links