Returning multiple values from function

Started by DoorKnobHandle, Wed 24/03/2010 01:39:51

Previous topic - Next topic

DoorKnobHandle

Are there any nice workarounds for when you have a function that does a bigger task and you need to return several basic variables (in my case, floats and ints)?

I didn't realize pointers to these types weren't allowed in AGS.

Usually I would create several functions that would all perform the task and just return a different variable but I'm talking about a process that is quite processor heavy and thus I really don't want people to have to call a function three times more than necessary just to get all the necessary values returned.

This is actually ultimately something for a plugin but that shouldn't really matter as the plugin-functions also have to follow AGS's script rules.

monkey0506

#1
AGS can return a dynamic array from a function, so as long as all the variables you're returning are the same type then you could reasonably do:

Code: ags
int[] some_func() {
  int arr[] = new int[5];
  arr[0] = 1;
  arr[1] = 5;
  arr[2] = 13;
  arr[3] = 27;
  arr[3] = 49;
  arr[4] = 74;
  return arr;
}


If you need mixed types of data you could consider using a String[] instead:

Code: ags
String[] some_func() {
  String arr[] = new String[3];
  arr[0] = "5";
  arr[1] = "13.0";
  arr[2] = "text";
  return arr;
}


Since there's currently no way to retrieve the size of a dynamic array I also recommend padding the array if it's of variable size/content-formatting, such as:

Code: ags
String[] some_func() {
  String arr[] = new String[4];
  arr[0] = "3"; // I tend to use the first slot in the array to indicate the number of actual items stored in the array
  arr[1] = "5";
  arr[2] = "13.0";
  arr[3] = "text";
}

DoorKnobHandle

#2
Ah, okay. I need floats and ints.

Well, putting that into a c++ plug-in is going to be a major pain in the behind (if it all possible).

Also, the way with returning a String[] is really, really user unfriendly for a plug-in designed to be used by the most people possible, I guess, right?

Hm, damn, doesn't sound too good.

Thanks though! :D

EDIT: Hang on, just had an idea. Couldn't I at least get it to work (even if not pretty and ultimately not what I'd want newer users to have to cope with) by just having my parameters be pointers to Strings? I'll try that out. I mean like this:

Code: ags

function DoSomething (String *destination, String *x, String *y )
{
   destination = "base";
   x = "5.5";
   y = "3";
}


Would that work?

monkey0506

Well String is internally declared as using an automatic pointer so if you put String* in AGS then it's going to convert it into String** which will cause an error at compile-time.

Also because of this behaviour, you can't change the value of a String passed as a parameter in AGS, so you would have to make it return a single modified String.

What you could consider doing is using a single string value with some form of delimiter and then just splitting the string based on that. That's the basic principle I built my Stack module on.

Crimson Wizard

I would go for using formatted String as in monkey's Stack module, OR using dummy variables in global scope... If there are only 3-4 of them needed, that won't hurt a single bit.

PS. lol, just invented a gag. It won't hurt a single bit... it would hurt 8 bits, or how much do you need to store your return values  ;D :=

Khris

As a cheap workaround:

Code: ags
float f, g, h;
int i, j, k;

void Module.CPU_killer() {
  ...
  f = result1;
  g = result2;
  h = result3;
  i = result4;
  ...
}

int Module.Get_i() {
  return i;
}


Not pretty but will do the job.

DoorKnobHandle

That would work except in my case I'm dealing with a plug-in, not a module. ;D Those can't have global variables as far as I know.

Anyways, I have found another workaround. I basically have a structure in my plug-in that contains all the ints and floats I need to pass to the user. Then my main function is called once and internally creates one of these mega-structures (and returns an int-handle to the std::vector in the plug-in). The user can then use that handle to get the single values with various functions. Every frame the std::vector of structures are erased so they only stay valid for one frame.

Better than nothing, I guess, but one heck of an additional workload for something that trivial in nature. :D

I assume we have already pestered CJ about this enough, haven't we?

SMF spam blocked by CleanTalk