Returning multiple values

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
AnonymousTipster
Posts: 197
Joined: Fri Jul 01, 2005 2:50 am

Returning multiple values

Post by AnonymousTipster »

This seemingly should be trivial, but i'm trying to get a function to return multiple values. I've tried both approaches:

Code: Select all

unsigned char *loadPNGfromfile(const char *filename,int *widp, int *heip, int swizzleit){widp = 10;heip=10;}

/*called like:*/
charstr = loadPNGfromfile("dir",&width,&height);
Which compiles fine, but width and height do not change.

Code: Select all

unsigned char *loadPNGfromfile(const char *filename,int &widp, int &heip, int swizzleit){widp = 10;heip=10;}

/*called like:*/
charstr = loadPNGfromfile("dir",width,height);
This is the way i'd prefer to do it, but it calls up an error: syntax error before '&' token.

Is this different in GCC, or have I made a mistake somewhere?

Makefile:

Code: Select all

TARGET = browser
OBJS = main.o p_sprint.o

INCDIR = "/home/Paul/pspgames/freetype/include"
CFLAGS = -O2 -G0 -Wall -I../curl/include -L../curl
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)

LIBDIR =
LDFLAGS =
LIBS= -lcurl -lpsp_req -lpspdebug -lpspsdk -lpspwlan -lpspnet_apctl -lpspnet_resolver -lc -lpspnet_inet -lpspnet -lstdc++ -lpspgum -lpspgu -lpng -ljpeg -lz -lm -lfreetype -lpsppower


EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = Eclipse
PSP_EBOOT_ICON = "icon0.png"
PSP_EBOOT_PIC1 = "eclipsebg.png"

PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Post by Raphael »

Your first aproach is the correct one, with *widp/*heip as parameters, however since you gave the function pointers to the ints, you cannot change their values with widp = xx as this will only change the address of the pointer. You should use *widp = 10; *heip = 10; and it should work.

Your second aproach is illegal in every C/C++ compiler, as the & operator gives the address of a variable and this is always a defined value or 0 if the variable is not allocated. As such, this cannot be a parameter of a function (since the compiler would expect the addres to the variable in the parameter list, but at the time of declaration, this is not allocated or even defined).

Well, I'm rather bad at explaining complicated stuff like pointer functionality... but I hope you got the point :)
memon
Posts: 63
Joined: Mon Oct 03, 2005 10:51 pm

Post by memon »

The first piece of code propably crashes your program, and the second does not work because your compiling a .c file.... I guess :)

The reason the first one does not work is that it is overriding the address, not storing the value to the address pointed by the pointer. The first should be:

Code: Select all

unsigned char *loadPNGfromfile(const char *filename,int *widp, int *heip, int swizzleit)
{
  *widp = 10;*heip=10;
} 
The second should work if you just change the extension to .cpp, then it'll be compiled using g++.

[edit] You may consider using a structure or a class to hold the data, should make your interface cleaner, like:

Code: Select all

PNGImage* img = loadPNGfromfile(const char *filename, int swizzle);
...
releasePNG(img);
AnonymousTipster
Posts: 197
Joined: Fri Jul 01, 2005 2:50 am

Post by AnonymousTipster »

Well, I replaced widp = 10; with *widp = 10; but that now crashes the PSP. That's still with .c by the way (it needs tweaking to compile in c++).

You call the function with &width, which passes a pointer to the variable, when the function recieves it with *widp, does it then revert it back into an integer, or is it still a pointer to an integer?
jsgf
Posts: 254
Joined: Tue Jul 12, 2005 11:02 am
Contact:

Post by jsgf »

It's still a pointer to an integer.

Code: Select all

*widp = 10;
means "write 10 into the memory pointed to by widp".
Garak
Posts: 46
Joined: Wed Jul 27, 2005 1:59 am

Post by Garak »

Hello,

Actually, Your second approach should work just fine.

unsigned char *loadPNGfromfile(const char *filename, int &widp, int &heip, int swizzleit) {widp = 10;heip=10;}

/*called like:*/
charstr = loadPNGfromfile("dir",width, height, 0); // added 0 as last param

You are just passing in your 2 ints by reference, so any changes to them made in your function will be reflected in main. However pass by reference was not around in straight C, so if you are using gcc to compile, you will get an error. In fact, you would need to make sure your file has a .cpp extenison, and use the C++ compiler to make that code compile correctly. But it is legal to pass values as you have done in the example above.

If that did crash, the likly culprit is that you are returning a pointer to a string you create locally within your function. Make sure you use new/malloc to allocate whatever it is you are returning as a string from your function. Otherwise, there is no telling what will actually be returned.

Garak
AnonymousTipster
Posts: 197
Joined: Fri Jul 01, 2005 2:50 am

Post by AnonymousTipster »

I'd like to do this in C, because porting to C++ would mean changing the way i've setup function pointers and changing other things that C++ doesn't like.

Here is some source for C:

Code: Select all

// implementation:
int parseInt(const char *str, bool *success) {
	const char *s = str;
	int r = 0;
	while (*s) {
		char c = *s;

		if &#40;&#40;c < '0'&#41; || &#40;c > '9'&#41;&#41; &#123;
			*success = false;
			return 0;
		&#125;
		r = r * 10 + &#40;c - '0'&#41;;
	&#125;
	*success = true;
	return r;
&#125;

// invocation&#58;
bool s;
int v = parseInt&#40;"2004", &s&#41;;
Obtained from http://www.kdedevelopers.org/node/321

So here, we have *var on the input of the function descriptor and within the function itself, and &var when we call the function. That is for C, yet when I try to do that, it crashes, suggesting that i'm actually writing to a pointer.
Does GCC treat these in a different way? Because i'm definitely doing it the same way as that site, but i'm getting a crash.

N.B, I know the rest of the function is sound, because changing *widp=10; to widp=10; (same for heip) doesn't crash, but doesn't return the values either.
jsgf
Posts: 254
Joined: Tue Jul 12, 2005 11:02 am
Contact:

Post by jsgf »

Something else is going on. If you compile with "-O -Wall", do any warnings come up?
Garak
Posts: 46
Joined: Wed Jul 27, 2005 1:59 am

Post by Garak »

That function to convert a string to an integer is not correct. It should be as follows:

// implementation:
int parseInt(const char *str, bool *success)
{
const char *s = str;
int r = 0;
while (*s)
{
char c = *s;
if ((c < '0') || (c > '9'))
{
*success = false;
return 0;
}
r = r * 10 + (c - '0');
s++; // I am the missing piece. Without me you have an endless loop
}
*success = true;
return r;
}

What is the exact function you are having problems with, and can we get the complete function, prototype, and an example of you calling it? If the function is simply the one from your origional post, the C version should not compile, as you are not passing the correct number of paramaters to it in your sample call.

Garak
AnonymousTipster
Posts: 197
Joined: Fri Jul 01, 2005 2:50 am

Post by AnonymousTipster »

Ok, well I spent the last half an hour isolating the function from my code, and i've managed to get it to work now (with the previous code snippet). I'm hoping that I just made a slip somewhere else, and it's not that 'compiler ram shuffle' problem that I had before.

Thanks for your help.
Post Reply