[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [sc-dev] writing primitives



On Monday, November 25, 2002, at 07:41 PM, James McCartney wrote:
those two args appear to be at :

	PyrSlot *defaultPath = g->sp;
	PyrSlot *prompt = g->sp + 1;

g->sp - 1 is the class File

All offsets from the stack pointer g->sp should be negative. If you are getting values at positive offsets, then you have declared the number of arguments incorrectly in definePrimitive() or in the method.

	//returns an array of strings for the file's full paths
	// nil if cancelled
	*prGetPathsDialog { arg defaultPath="",prompt="";
		_File_GetPathsDialog
		^this.primitiveFailed;	
	}

...

void initCocoaFilePrimitives()
{
	int base, index;
	
	base = nextPrimitiveIndex();
	index = 0;

definePrimitive(base, index++, "_File_GetPathsDialog", prGetPathsDialog, 2, 0);
}


and these are the two args:

	PyrSlot *defaultPath = g->sp;
	PyrSlot *prompt = g->sp + 1;

-1 is the receiver which is the class File

anything look wrong ?


g->sp is the top of the stack and is the last argument pushed. g->sp - inNumArgsPushed + 1 is the receiver and where the result goes.

that's where the result should be placed ?
ah like this...

		if ...

			PyrString *string = newPyrString(g->gc, (char*)pathname, 0, true);
			SetObject(a, string);
		} else {
			SetNil(a);
		}


i'm getting an array of files via cocoa, which was easy as hell. took 3 minutes to figure out.
made an sc-array, filled the slots.  that took an hour.

some guidelines:

thank you for those.


If possible, you should avoid creating objects in a primitive. Primitives are much simpler to write and debug if you pass in an object that you create in SC code and fill in its slots in the primitive.

When you do fill in slots in an object with other objects, you must call g->gc->GCWrite(obj, slot) in order to notify the garbage collector that you have modified a slot that it may have already scanned.

and SetObject doesn't do that. the GC isn't even aware of my object yet, right ?

i'm setting slots on my new object:

            putIndexedSlot(g ,scArray,(PyrSlot*)pyrPathString  ,count);


		so after setting each slot do i have to call
			g->gc->GCWrite(scArray, slot);
		?

or does this only matter after i've put it into the receiver / stack position ?



Do not store pointers to PyrObjects in C/C++ variables unless you can absolutely guarantee that they cannot be garbage collected. For example the File and SCWindow classes do this by storing the objects in an array in a classvar. The object has to stay in that array until no C object refers to it.

Failing to observe the above two points can result in very hard to find bugs.

If you create more than one object in a primitive you must make sure that all the previously created objects are reachable before you allocate another. In other words you must store them on the stack or in another object's slots before creating another.

so i should put the scArray into the receiver straight away.
then for each:
	put slot,
	g->gc->GCWrite()
?

Creating objects can call the garbage collector and if you have not made your objects reachable, they can get collected out from under > you.


now where do i put the thing to return it ?

into g->sp - inNumArgsPushed + 1.
In most primitives this is referred to by the variable 'a'.

--
--- james mccartney james@xxxxxxxxxxxxxx <http://www.audiosynth.com> SuperCollider - a real time synthesis programming language for the PowerMac.
<ftp://www.audiosynth.com/pub/updates/SC2.2.16.sea.hqx>

_______________________________________________
sc-dev mailing list
sc-dev@xxxxxxxxxxxxxxx
http://www.create.ucsb.edu/mailman/listinfo/sc-dev



-felix