Search code examples
cphp-extension

Wrapped method ends up in the 'false' block as but direct function call doesn't


Note: I come from a Python / PHP related background and don't have too much experience with C.

I'm currently writing a PHP extension that needs to check if another module is loaded, for this I've copied and pasted the following snippet of code throughout my extension:

#include "php.h"

const char* name = "hash";

if (zend_hash_str_exists(&module_registry, name, sizeof(name) - 1)) {
    return; // Doesn't end up here, module is loaded
}

// Returns true and thus ends up here

I decided to put this into it's own method to make my code a lot more clean, however whenever I do this, the method seems to return FALSE or NULL. This is the method I'm using:

#include "php.h"

zend_bool extension_module_exists(const char* name)
{
    return zend_hash_str_exists(&module_registry, name, sizeof(name) - 1);
}

const char* name = "hash";

if (extension_module_exists(name) == false) {
    return; // Now I end up here
}

Could someone give me an indication of what I might be doing wrong? Thank you.


Solution

  • I don't think your first version works, either, as it is shown here. Chances are you have

    const char name[] = "hash";
    

    instead of

    const char* name = "hash";
    

    The code is wrong because sizeof() does something different than you seem to expect. It returns the actual storage size of its argument, and if this argument is a pointer, the size returned is the size of the pointer, not that of the object it points to.

    For the length of a string, there's the function strlen() in string.h, you should use this instead of sizeof().

    Example:

    zend_bool extension_module_exists(const char* name)
    {
        return zend_hash_str_exists(&module_registry, name, strlen(name));
    }
    

    Note this comes with a little overhead, as strlen() must scan its argument to find the first 0-byte, which marks the end of a string in C.


    That being said, you should probably think about restructuring your module to only once check for the other extension and save the result in a variable.