# Storing zvals in hash tables in resources

- Thread: https://externals.io/message/49958
- Original archive: https://news-web.php.net/php.internals/49958
- Started by Martin Jansen on 2010-10-22T21:22:06+00:00
- Messages: 3
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #49958 — Martin Jansen — 2010-10-22T21:22:06+00:00

URL: https://externals.io/message/49958#49958

I'm trying to store zvals in a hash table which is part of a resource.
Unfortunately the zvals do not seem to "persist" between function calls:

<?php
$ctx = foo_create_context();
foo_assign_value($ctx, "foo", "bar");

// prints NULL:
var_dump(foo_get_value($ctx, "foo"));
?>

Please see my code below.  In foo_get_value zend_hash_find() does *not*
return FAILURE, so the key is there while the value is gone.  Can
someone spot my mistake?

- Martin

typedef struct _foo_context {
    HashTable *variables;
} foo_context;

PHP_FUNCTION(foo_create_context) {
    foo_context *ctx;
    ctx = emalloc(sizeof(foo_context));

    ALLOC_HASHTABLE(ctx->variables);
    zend_hash_init(ctx->variables, 32, NULL, NULL, 0);

    ZEND_REGISTER_RESOURCE(return_value, ctx, le_foo_context);
}

PHP_FUNCTION(foo_assign_value) {
    foo_context *ctx;
    zval *zcontext;
    char *name;
    int name_len;
    zval *value;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz",
        &zcontext, &name, &name_len, &value) == FAILURE)
    {
        return;
    }

    ZEND_FETCH_RESOURCE(ctx, foo_context*, &zcontext, -1,
        FOO_CONTEXT_RES_NAME, le_adl_context);

    zend_hash_update(ctx->variables, name, name_len + 1, &value,
sizeof(zval*), NULL);
}

PHP_FUNCTION(foo_get_value) {
    foo_context *ctx;
    zval *zcontext;
    char *name;
    int name_len;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs",
        &zcontext, &name, &name_len) == FAILURE)
    {
        return;
    }

    ZEND_FETCH_RESOURCE(ctx, foo_context*, &zcontext, -1,
FOO_CONTEXT_RES_NAME, le_foo_context);

    zval **value;
    if (zend_hash_find(ctx->variables, name, name_len + 1,
(void**)&value) == FAILURE) {
        return;
    }

    RETVAL_ZVAL(*value, 1, 0);
}

---

## #49959 — Gustavo Lopes — 2010-10-22T23:05:29+00:00

URL: https://externals.io/message/49958#49959 · In reply to: #49958

On Fri, 22 Oct 2010 22:22:06 +0100, Martin Jansen <martin@divbyzero.net>  
wrote:

> I'm trying to store zvals in a hash table which is part of a resource.
> Unfortunately the zvals do not seem to "persist" between function calls:
>
> [...]
>
>     ALLOC_HASHTABLE(ctx->variables);
>     zend_hash_init(ctx->variables, 32, NULL, NULL, 0);
>

You probably want to give a destructor to zend_hash_init, since you're  
storing zvals, that would be ZVAL_PTR_DTOR.

> [...]
>     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz",
>         &zcontext, &name, &name_len, &value) == FAILURE)
>     {
>         return;
>     }
>
>     ZEND_FETCH_RESOURCE(ctx, foo_context*, &zcontext, -1,
>         FOO_CONTEXT_RES_NAME, le_adl_context);
>
>     zend_hash_update(ctx->variables, name, name_len + 1, &value,
> sizeof(zval*), NULL);

You're not incrementing the refcount of the value you're adding to the  
hash table. Call zval_add_ref.


-- 
Gustavo Lopes

---

## #49960 — Martin Jansen — 2010-10-23T06:29:14+00:00

URL: https://externals.io/message/49958#49960 · In reply to: #49959

> On Fri, 22 Oct 2010 22:22:06 +0100, Martin Jansen <martin@divbyzero.net>
> wrote:
> 
> > […]
> 
> You probably want to give a destructor to zend_hash_init, since you're
> storing zvals, that would be ZVAL_PTR_DTOR.
> 
> You're not incrementing the refcount of the value you're adding to the
> hash table. Call zval_add_ref.

Those two hints seem to do the trick. Thanks!

- Martin
