SC2 API/Structs

From SC2Mapster Wiki
Jump to: navigation, search

Structs[edit | edit source]

Structs are data structures which hold other relevant pieces of information.

Defining A Struct[edit | edit source]

Let's say I want to have a monkey and track the number of bananas it has and also how much poo the monkey has flung thus far.

struct Monkey {
    int numBananas;
    int pooFlung;
}; // ending semicolon is important

There I defined a struct named Monkey that has a two fields: int numBananas and int pooFlung. To make a new Monkey, all that needs to be done is to declare Monkey myMonkey;

Creating a struct "properly"[edit | edit source]

Unlike some other languages (C++, Java, C#, Python), Galaxy lacks the concept of constructors, so all fields in a struct are initialized to their default values (0 for int, false for bool, etc.). One way we can get around this is by declaring by convention a pseudo-constructor:

void Monkey_Initialize(Monkey* self, int numBananas) {
    self->numBananas = numBananas;
    self->pooFlung = 0; // should already be 0, this is just for sanity's sake.
}

This new function will initialize a Monkey with the given number of bananas.

Monkey misterTeeny;
Monkey_Initialize(&misterTeeny, 10);
// Mr. Teeny is a monkey with 10 bananas.
print(misterTeeny.numBananas); // 10
print(misterTeeny.pooFlung); // 0

Pointers, References, and Values[edit | edit source]

Monkey teenyClone = misterTeeny; // error: bulk copy not supported
// This doesn't work in galaxy code because it can't make the copy.
Monkey* teenyPointer = &misterTeeny; // pointer
// this will create a pointer to the real misterTeeny
// such that if I edit misterTeeny, teenyPointer will
// reflect the changes and vice-versa.
Monkey* otherPointer = teenyPointer; // same as above
// exact same as teenyPointer, also a pointer to the
// real misterTeeny.
misterTeeny.numBananas = 5;
print(teenyPointer->numBananas); // 5
// Pointers access fields through '->' rather than '.'
otherPointer->numBananas = 15;
print(misterTeeny.numBananas); // 15
  • Non-pointer structs assign to each other with copy semantics, but pointer-based structs keep the same references.
  • Galaxy doesn't allow dynamic memory allocation, so we can't just use pointers everywhere. We also can't just use values everywhere, either.
  • Function parameters must take either simple, native types (int, string, fixed, etc.) or pointers to structs.
void Monkey_GiveBananas(Monkey* self, int numBananas) {
    self->numBananas += numBananas;
}
void Monkey_FlingPoo(Monkey* self) {
    print("Flinging monkey poo!");
    self->pooFlung += 1;
}
Monkey bingo;
Monkey_Initialize(bingo, 0);
print(bingo.numBananas); // 0
Monkey_GiveBananas(&bingo, 5);
print(bingo.numBananas); // 5
print(bingo.pooFlung); // 0
Monkey_FlingPoo(&bingo); // Flinging monkey poo!
print(bingo.pooFlung); // 1
  • It's important not to keep around pointers to dead values, as that can cause a stack error.
  • Example of what NOT to do:
Monkey* MakeMonkey() {
    Monkey monkey;
    return &monkey; // this will work for a split-second
    // until the function is complete, at which point the
    // memory for the "monkey" variable will be reclaimed
    // and any access on this pointer will cause an error
}
print(MakeMonkey()->numBananas); // Error!

Structs containing other structs[edit | edit source]

  • Along with native types, structs can contain other structs, as long as the inner struct is declared before the outer one and you can't declare one struct inside itself.
struct Apple {
    string name;
};
struct Tree {
    Apple apple;
};
Tree tree;
tree.apple.name = "Gala";
Invalid example:
struct Tree {
    Apple apple; // Error, Apple doesn't exist yet.
};
struct Apple {
    string name;
};
struct Tree {
    Tree tree; // Error, can't declare inside yourself
};
  • This does work, though
struct Link {
    int value;
    Link* next;
};