Re: Relationship between IoTag and IoObject
Steve Dekorte <[email protected]>
| Newsgroups | gmane.comp.lang.io |
|---|---|
| Message-ID | <[email protected]> |
On 2011-06-04 Sat, at 09:28 PM, dennisf486 wrote:
> I've been working for a while with Io as an embedded interpreter in C++ programs with my LikeMagic binding library, but there are still some things I don't understand. (As Joshua Cearley said, the documentation for embedding Io leaves something to be desired; unfortunately those of us with the most to gain from the documentation existing don't have the knowledge of what to write for it!)
>
> One thing in particular I don't understand is what is the architectural relationship between IoTag and IoObject in the implementation of Io? And the relation of IoTag to CFunction?
>
> I can see that:
> IoObject is a typedef for CollectorMarker
> CollectorMarker has a pointer to IoObjectData
> IoObjectData has a pointer to IoTag
>
> What was the reason to have some fields in IoTag versus just putting them all in IoObjectData? Are there many IoObjects to one tag, or is it one-to-one? Is IoTag kind of like a "type"?
IIRC, a tag is shared by all the instances. It's sort of like a very, very primitive class that only has methods for things like slot lookups, message sends and garbage collection hooks. I think I named it Tag because IIRC, it's similar to what Lua called tags (previously "hooks").
> I see functions for adding CFunctions with or without IoTags. How is a CFunction without an IoTag different from one with? Is a CFunction also an IoObject, or is a CFunction with an IoTag unrelated to an IoObject with an IoTag? Can I create CFunctions with IoTags in a CFunction factory and use setSlot to attach them where they go?
An IoCFunction (like the other atomic prototypes) is just a clone of IoObject with a custom tag. You can't not have a tag on an object IIRC - you could set it to be the same tag as an IoObject though, in which case it would behave just like an IoObject, AFAICS.
> I'm particularly interested because for my C++ binding library, it would be useful to be able to stuff an extra void* object into my CFunctions, distinct from the the target function pointer itself. I'm hoping IoTag might be one way to do that.
I don't recommend this. I'd recommend creating an OO binding instead. You might check out some of the other Io addons for examples.
>
> The assumption with CFunctions seems to have been that you would have a unique CFunction for every unique thing you want to do, but for my C++ bindings library I find it more convenient to have a single function in C that is my only entry point from Io, and from there branch out to whatever C++ object & method should be invoked. Currently I do this by examing the name of the message I receive to figure out what method should actually be called, but this string lookup is not so efficient. What I'd much rather do is be able to embed a pointer to my C++ CallTarget object in a void* inside the CFunction; then in my entry point I can just cast the void* to CallTarget and call CallTarget::eval(); no lookup needed.
>
> I think what I want is a "void* user_data;" item right under "void* state;".
I'd recommend just copying at a simple addon like the User addon, changing it's name and then modifying it to do what you want:
https://github.com/stevedekorte/io/tree/master/addons/User/source
Basically, you write a C function (Not a IoCFunction) for each function you want to bind, e.g:
IoObject *IoUser_protoName(IoUser *self, IoObject *locals, IoMessage *m)
{
TCHAR userName[256];
DWORD userSize = 255;
GetUserName(userName, &userSize);
return IOSYMBOL(userName);
}
And make them a slot on your object when you set up it's proto:
IoUser *IoUser_proto(void *state)
{
IoObject *self = IoObject_new(state);
IoObject_tag_(self, IoUser_newTag(state));
IoState_registerProtoWithFunc_(state, self, IoUser_proto);
{
IoMethodTable methodTable[] = {
{"name", IoUser_protoName},
{"homeDirectory", IoUser_homeDirectory},
{NULL, NULL},
};
IoObject_addMethodTable_(self, methodTable);
}
return self;
}
> While I'm looking at IoTag: what is the difference between performFunc and activateFunc? What is the difference between performing and activating in Io?
performFunc handles slot lookup and then calls activateFunc and v only handles a direct activation.
e.g. if you want to change how lookup works, override performFunc. If you want to just change how activation works, override activateFunc.
Cheers and I hope this helps,
Steve