Ok, the situation is somewhat clearer now. But I think you're going in the wrong direction. The underlying data structures may (and most likely will) change even between betas of ZE2, and these APIs may be altered too... Other than the (obvious) lack of warm fuzzy feeling, wouldn't invoking the compiler using zend_eval_string() make more sense? With smart strings or output buffering, creating this PHP snippet should be easy, and would give you the best results, don't you think..?

If you have a good reason not to go with it, I guess we could add them to the API with clear comments saying that they should really NOT be used by extensions...

Zeev

At 16:30 31/07/2003, Mark Spruiell wrote:
>>Can I assume from the lack of an enthusiastic response that my
>>use case doesn't really justify the changes I requested? :)
>
> Not necessarily - I didn't quite understand why register_internal_class
> doesn't work for you, and didn't have enough time to dive into it.  If you
> can elaborate a bit about it (provide an example, etc.), it'd help.

OK, you asked for it. ;)

I'm prototyping an Ice extension for PHP. Ice is our middleware,
similar in concept to CORBA. Like CORBA's IDL, Ice has a specification
language called Slice. For example:

struct Contact
{
    string name;
    string address;
};

interface Phonebook
{
    void add(Contact c);
};

As I mentioned, the traditional approach would be to translate these
definitions into PHP code, supported by an extension that provides
some core classes.

However, since Ice provides a library for parsing the specification
language, we decided to take a different approach. The PHP extension
uses the Slice parser to read in the type definitions at module startup.
Before each request, the parse tree is descended and PHP user classes
are created where appropriate. This means that scripts can refer to
the Slice types by name, just as if the types had been first translated
to PHP and then parsed by the interpreter.

For example:

$phonebook = ...
$contact = new Contact;
$contact->name = "John Q. Adams";
$contact->address = "D.C.";
$phonebook->add($contact);

There are several advantages to this approach:

- It's simple to use and administer. The script writer doesn't have
  to bother with generating PHP code from his Slice types, or worry about
  the generated code getting out of sync with the Slice types, etc. All
  he needs is the extension and the Slice files.

- Scripts are faster. The majority of the time-consuming work, such
  as marshaling data for a remote invocation, is done by the extension,
  and not in PHP.

I initially tried to create internal classes for the Slice types,
because it meant the classes could be created once, at module startup,
and not repeatedly before every request. However, I soon found out that
it wasn't appropriate:

- Internal classes cannot be extended by user classes. Slice has
  class and interface types that can be implemented locally, therefore
  user code must be able to extend the classes created from the
  Slice types.

- Internal classes cannot have default properties. I wanted to add
  default properties for Slice data members, but default properties
  are assumed to be created using the e* allocation functions,
  which isn't compatible with internal classes.

It's clear that the Zend API didn't really intend for extensions to
create user classes, but the only trouble I encountered in doing this
was when I attempted to create function prototypes for Slice interface
methods. When I tried to subclass a Slice type in PHP and implement
a method, an error would occur because the function definition didn't
match the prototype. It turns out that Zend is comparing opcodes as
well, which my extension wasn't creating for the function prototypes.
The solution was to skip the creation of function prototypes. It's not
ideal, but it's also not a serious problem for us.

The only reason we can get away with creating user classes at runtime
is because we don't have complex requirements for the user classes:

- A Slice struct becomes a PHP class with default properties for each
  declared data member.
- A Slice interface becomes an empty PHP interface.
- A Slice class becomes a PHP class with default properties for
  each declared data member.
- A Slice enum becomes an empty PHP class with constants for each
  enumerator.

The remaining Slice types map to native PHP types.

I can understand your reluctance to export these functions. It's not
reasonable to expect an extension would want or need to perform all of
the duties of the PHP compiler. For our limited requirements, however,
the API is sufficient aside from the lack of these two functions on
Windows.

Sorry for the long-winded explanation. I hope I've described our situation
more clearly now.

- Mark


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Reply via email to