4

I'm doing some experiments with Phalcon Zephir to see how well it can convert some of my libraries to PHP extensions.

I have two PHP classes, each already defined in its own file: the Zephir notes are quite clear that this must be the case.

trienode.zep

namespace tries;

class trienode
{
    public children;

    public valueNode = false;

    public value = null;

    public function __construct()
    {
        let this->children = [];
    }
}

and

trie.zep

namespace tries;

class trie {

    private trie;

    public function __construct() {
        let this->trie = new trienode();
    }
}

But whenever I try to compile the classes using zephir compile, I get

Warning: Class "trienode" does not exist at compile time  in /home/vagrant/ext/tries/tries/trie.zep on 8 [nonexistent-class]

            let this->trie = new trienode();
    ---------------------------------------^

(and if I continue through the build process, and install the resultant .so file, it errors when I try to use it from within a PHP script)

<?php

namespace tries;

$test = new trie;

giving

PHP Warning:  PHP Startup: Unable to load dynamic library '/usr/lib/php5/20121212/tries.so' - /usr/lib/php5/20121212/tries.so: undefined symbol: zephir_tries_trie_init in Unknown on line 0
PHP Fatal error:  Class 'tries\trie' not found in /home/vagrant/triesTest.php on line 5

I've looked through the Zephir documentation, and various blog posts, but can't find any examples of building an extension that comprises more than a single class file.

Has anybody succeeded in building an extension using Zephir that does comprise more than a single class? And if so, what settings or configuration options (or additional steps) does it require to build a working so?

apaderno
  • 28,547
  • 16
  • 75
  • 90
Mark Baker
  • 209,507
  • 32
  • 346
  • 385
  • The question is, how debuggable and maintainable will be the result of that - even if it once compile well? – hek2mgl Jan 25 '14 at 10:47
  • @hek2mgl - That's why I'm experimenting to find out – Mark Baker Jan 25 '14 at 15:57
  • :) you already got me, now I'm experimenting myself with this.. Need to organize some stuff, will have a look later here. – hek2mgl Jan 25 '14 at 16:06
  • @Hek2mgl - it has its quirks as a language, so it's taken me a while to identify why my code wasn't working as it should.... but my Zephir Trie classes now load a 160k dictionary in 43 seconds compared with 96 seconds for the pure PHP version, and do a search in 0.7 seconds compared with 1.1 seconds for the pure PHP.... memory about 0.1% higher (but that's something I can probably address to get at least parity) – Mark Baker Jan 25 '14 at 18:36
  • Thanks for the feedback, I must admit that I didn't more than cloning Zephir and reading the README today. Normally I'm not such a friend of too much tweaking techniques because I think it is often misused. Developers should get a feeling of how performant untweaked code can be - if well written. However, I'm sure that you are aware of that, so using some optimization - like Zephir - could really be interesting here. I'll check it these days (thx for pointing me towards Zephir, +1 ) .. Have you compared the results to hhvm? (maybe stupid question but hhvm is still on my list) – hek2mgl Jan 25 '14 at 20:22
  • It took a fair bit of reading the language documentation to convert my existing files. Some changes are simple, stripping `$` from variable names, making sure they're all declared before using them, prefixing assignments with `let`, etc. Control structures such as `foreach` are slightly more interesting - foreach($array as $key => $value) {}` becomes `for key, value in array {}`, which feels nice and clean. – Mark Baker Jan 25 '14 at 20:28
  • But a `while (value1 < value2) {}` loop simply didn't execute without moving the comparison outside of the statement and just comparing a single variable; and you can't reference characters in a string using `a[i]` or `a{i}` syntax; likewise it isn't happy with `i++`, though it accepts `let i++` which feels ugly, or `let i +=1` – Mark Baker Jan 25 '14 at 20:35
  • I'm still going to devote a bit of time and effort to exploring just what it's capable of though – Mark Baker Jan 25 '14 at 20:36
  • Thx for all that info, appreciating this! – hek2mgl Jan 25 '14 at 20:39

1 Answers1

4

It looks like the namespace has to be included in the call.

let this->trie = new tries\trienode();
//                   ^^^^^^

I didn't see this explicitly mentioned in the documentation, but is hinted at (pardon the pun) in the Return Type Hints section, which uses the namespace in the hints.

Changing your example class to that shown above allows the extension to compile as desired.

salathe
  • 51,324
  • 12
  • 104
  • 132
  • Thanks Peter... definitely one of the quirks of Zephir, the namespace declaration seems to be purely for the benefit of the compiler bundling the classes into a package, and all namespaced classes referenced in the code seem to need absolute namespacing – Mark Baker Jan 25 '14 at 18:31