In the last post, we started with the implementation of the constructor and one method. Next up, let’s do a bunch more.
Part 4: Populating our store
Let’s take a look at the source from this commit: https://github.com/jaytaph/phpshout/blob/8675c69c27675d4e1159a754a634f08fffc07746/shout.c
You see there is something changed in our store on line 40: there is a pointer to a shout structure. This structure is used by the shout library so every time we create a new object store, we should also initialize a shout object. You will see that things have changed in the constructor method on line 85. We fetch the actual store, and create a new shout object by issuing a shout_new(). If something goes wrong, and the shout object is NULL, we throw an exception.
Because we are adding things to our store, we must also make sure these structures gets freed when we don’t need them anymore. So in our shout_object_free function (line 225), we also free our shout structure by calling shout_free().
If you look closely to this file, you will see that something also has changed on line 352. Here we actually set the handler for cloning objects to NULL, meaning we can’t clone the object (try it, it will fail now). This is done because when we need to clone, we should also clone our internal data like the shout structure. Unfortunately, this data is very complex which means we need to copy over all the data, but also duplicating some of this data (because otherwise we end up changing data in two different places, for two different objects, which is the whole point of cloning to get rid of). So instead of dealing with this issue, I’ve decided to not allow cloning at all for the time being.
Also another thing that has changed, is that i’ve implemented a PHP_MSHUTDOWN function on line 386, and added this to the module entry structure on line 409. This will call the shout_shutdown(), to make sure things gets shutdown properly.
Part 5: Add getters.
A lot of the libshout functionality are actually based on getting and setting information, just like “normal” PHP getters and setters. This shout.c file actually has two ways of dealing with getting values which I will show you both.
The first method is the easiest to explain. Take a look at line 194, where there is a get_host PHP_METHOD.
Since getting stuff do not require any php parameters, the zend_parse_parameters_none() will check if there are any. If so, the php method will return false. On line 201, it will load the internal store. Line 202 will return a string value with the host as returned by the shout_get_host() function. This function needs a shout_t structure, which is the one we are saving in our store. From a PHP point of view, nobody needs to know anything about this shout_t structure so all this is done internally. As said, it will return a string with the current host.
Let’s take a quick look at setting info as well. Line 205 creates a set_host method. In this case, we DO need parameters, namely a string from PHP, which is the host we need to set. Line 210 will parse the parameters we get from PHP, makes sure we only get 1 string (that is the “s”), and this information is placed in the “host” and “host_len” variables. Remember I was talking about binary safe strings? The host is just a block of data which may or may not have \0 in them. The host_len is a integer that actually holds the length of the string. If we are really correct, we cannot assume that we can just use the “host” as a normal string because it isn’t. But for now this doesn’t matter, if you want to set a non-binary safe string as a host, that is perfectly fine, but just don’t think it will work that way:
$shout->set_host("Not a binary\x00 safe string");
print $shout->get_host(); #returns: "Not a binary"
Line 215 will actually set the host name by supplying our shout-t structure and the (non-binary-safe) host string. As a result, it will return a status code (the RET_* constants), which are LONG values, hence the RETURN_LONG. Notice that we don’t need to duplicate longs just like we need to do with RETURN_STRING.
Now, back to the getters, as you can see they are pretty easy to write, but in C, writing a function for each getter and for each setter would result in lots of duplicate code. There must be better ways to deal with this. And there is.
On line 95, I’ve added a (static) function called php_shout_get_handler_string. The argument list looks wierd, but again, it’s a ZEND macro:
static void php_shout_get_handler_string(INTERNAL_FUNCTION_PARAMETERS, const char *(*func)(shout_t *)) {

2 Responses to PHPShout : a shoutcast streamer in PHP: Part 3