Re: Re: Interested in Abstract Extension API and Dependency Interface
| From: | Graham Kelly | Date: | Tue, 31 Mar 2009 15:42:48 +0000 |
| Subject: | Re: Re: Interested in Abstract Extension API and Dependency Interface | ||
| References: | 1 2 3 4 5 6 7 8 9 10 | Groups: | php.pecl.dev |
| Request: | Send a blank email to pecl-dev+get-6276@lists.php.net to get a copy of this message | ||
Hi,
I don't see any good way to get around having to put the function prototypes
in the extension that wishes to use them. However, I feel this is still
better than needing a struct that could change from version to version as
function prototypes usually don't change often.
I was also wondering if you were going to be implementing a callback system.
I noticed your php_api_register_callback function but upon further
inspection this isn't exactly what I assumed it was. For example will there
be functionality to do the following:
Say an extension such as APC has an API function that allows for adding data
to one of the oparrays that it caches. APC has a user space functon
apc_cache_info that returns information about data in the cache. If another
extension wanted to store something like statistics about the op_array in
APC's cache along with the oparray then it might be useful to have a
callback in apc_cache_info's C implementation to allow for the extension to
make whatever modifications it needs (say add extra fields to the array that
apc_cache_info returns). The extension could on MINIT register a callback
with APC for this location and then when the function is called APC will
call the callback at the apropriate times.
It seems as if there are a few times when having this type of functionality
could be very handy to allow extensions to fully interact. However, there
are some issues with how registration would be resolved and what to do about
multiple extensions wishin to use the same callback point.
The problem with registering the callback on MINIT in the extension is that
the other extension with which it is registering it with would have to be a
dependancy and thus its MINIT would need to be called first. I suppose this
could be gotten around by using some type of registration handler (similar
to how ini values have handlers when the value changes). This seems a bit
messy to me though. The problem with multiple extensions wishing to use the
same callback point could be andled one of two ways: 1) if using the
handlers as described then just let those deal with the issue or 2) store a
list of all the callbacks for that point and just return the list when the
extension wants to make use of them.
Not sure if you have given that any thought, but I figured I would throw it
out there. Sorry if I'm complicating things here :-)
~ Graham Kelly
On Tue, Mar 31, 2009 at 10:54 AM, Varuna Jayasiri <vpjayasiri@gmail.com>wrote:
> Hi,
>
> Thank you very much for the comments :)
>
> On Tue, Mar 31, 2009 at 8:01 PM, Graham Kelly <sgkelly4@gmail.com> wrote:
>
>> Hey,
>>
>> Overall I think your application looked really good.
>
> Thanks :)
>
>>
>> I personally love the idea for this as the current way to share such
>> functions is really awkward. I do have a few comments on the overall design
>> though. i am a bit uncomfortable about the use of a struct to pass around
>> the functions. This leaves extensions needing to either awkwardly include a
>> header form that extension at compile time (thus requiring the extension to
>> be available on the machine its being compiled on) or to keep a copy of the
>> struct definition within the extension wishing to use it. Neither solution
>> seems all that great. The first is just awkward and will make building a
>> pain. If I were to build an extension I would need to have those other
>> extensions available and compiled on the same machine by the same compiler
>> (people usually don't switch compilers between extension builds, but it is
>> possible that some compiler out there might mess with the struct alignment
>> and not represent it the same way). Of course the second solution has the
>> same problems as the first (minus actually needed to have the extension).
>> However, the second option of just keeping a local copy of the struct
>> definition means the API maintainers really cant ever get rid of or
>> reorganize the struct. This doesnt seem to be much of an improvement over
>> the current hackish way this is being done now.
>>
>> I personally feel that fetching just one function at a time seems like the
>> better solution. The problem with this of course is that it would require
>> more function calls and more hash table lookups. But, I think this in
>> practice should be trivial. If extension dependancies could be resolved then
>> all that would need to be done is for the extension wishing to make use of
>> the API to retrive the pointer to the function on MINIT and save it
>> somewhere (probably its globals struct). Alternativly, If it is a one, or
>> few use call then the lookup could just be done directly before the call.
>> However, this then gets in to the issue with function prototypes. However, I
>> feel that these will change much less frequently than the struct might.
>> Also, I suppose API version could be used to select the correct function
>> prototype if it changed at runtime and cast/call it apropriatly.
>>
>
> Yes, this seems to be a better approach. So with this method, would the
> function prototypes be declared on the caller extension.
>
>
>> Should this be part of PHP or Zend? It seems to me that most extension
>> handling is done by Zend. Also, the names of some of the function names
>> sound a bit off to me (granted this is really just personal preference).
>> Something like php_exists_api migth be better as php_api_exists or even
>> better php_ext_api_exists. I noticed you used this naming style with the
>> callback function. Also, in php_regiser_api size should probably be of type
>> size_t. :-)
>
>
> Yes these should be changed :P. I should have proofread the application
> more carefully :P.
>
>>
>>
>> I really want to reiterate that I am very excited about the possibility of
>> having this functionality. There have been several times where this could
>> have simplified things a bit. Your application looked really good and I'm
>> sure you will have a lot of fun with GSoC. It really is a great program.
>>
>
> Thanks
>
>
>>
>> ~ Graham Kelly
>>
>
> Varuna
>
>>
>>
>> On Tue, Mar 31, 2009 at 5:56 AM, Varuna Jayasiri <vpjayasiri@gmail.com>wrote:
>>
>>> Hi,
>>>
>>> My Application
>>>
>>>
>>> http://www.xvpj.net/gsoc-09-application-php-abstract-extension-api-and-dependency-interface/
>>>
>>> Please comment on this and give suggestions for improvements.
>>>
>>> Thank you
>>> Varuna
>>>
>>> On Tue, Mar 31, 2009 at 8:31 AM, Varuna Jayasiri <vpjayasiri@gmail.com
>>> >wrote:
>>>
>>> > Hi,
>>> >
>>> > On Tue, Mar 31, 2009 at 7:49 AM, shire <shire@php.net> wrote:
>>> >
>>> >>
>>> >>
>>> >> Hi Varuna,
>>> >>
>>> >> Varuna Jayasiri wrote:
>>> >>
>>> >>> I think I might have misread something in the initial design section
>>> :P.
>>> >>> It says that a extension specific structure would be used, which I
>>> now
>>> >>> understand as different extensions registering different api
>>> structures;
>>> >>> i.e. there is no generic structure as extension_api_t but there are
>>> >>> different structures for each extension. This solves the above
>>> problem.
>>> >>>
>>> >>
>>> >> Yes exactly.
>>> >>
>>> >>
>>> >> However, if an extension specific structure is used, wouldn't
>>> exposing
>>> >>> it to other extensions be done at the compile time (via
>>> >>> PHP_INSTALL_HEADERS)? Won't this require testing out whether the
>>> >>> required extension is available using macros
>>> >>>
>>> >>
>>> >> Yes, this is a potential downside. I envisioned this being done in
>>> either
>>> >> the way you described with a simple header file check for an installed
>>> >> extension. Of course the pitfall with this approach is that you can't
>>> build
>>> >> an extension with a particular API support unless it's actually
>>> installed on
>>> >> the system.
>>> >>
>>> >> The other option I really had in mind would be for the calling
>>> extension
>>> >> to go ahead and include the prototypes it needs itself in it's own
>>> header
>>> >> files. While this of course defeats some goals of including a header
>>> file,
>>> >> but it's of a limited scope and multiple prototypes could be included
>>> for
>>> >> different extension versions so long as it's validated before use
>>> with.
>>> >
>>> >
>>> > Now I'm pretty clear on how this could be done :). I would go ahead
>>> with
>>> > the idea of including the prototypes in the caller's headers. I'll
>>> complete
>>> > the application with this design, and publish it for comments. I'll
>>> change
>>> > it if a better approach comes up in the next few days.
>>> >
>>> >
>>> >>
>>> >>
>>> >> So, isn't it convenient to use dynamic registration as I previously
>>> >>> described, with an improvement to overcome the efficiency issue.
>>> >>> e.g. (rough)
>>> >>>
>>> >>> /to register/
>>> >>>
>>> >>> PHP_API_FE(func) {#func, zif_##func}
>>> >>> php_api_functions func_set[] = {
>>> >>> PHP_API_FE(fetch),
>>> >>> PHP_API_FE(store)
>>> >>> };
>>> >>>
>>> >>> php_register_api(&api, func_set)
>>> >>>
>>> >>> /to retrieve/
>>> >>>
>>> >>> PHP_API_FUNCTION fetch = php_get_api_function("myextension",
>>> >>> version,
>>> >>> "fetch");
>>> >>> fetch(key);
>>> >>>
>>> >>> /or/
>>> >>>
>>> >>> PHP_API_FUNCTION_SET apc_api =
>>> >>> php_get_api_function("myextension",
>>> >>> version);
>>> >>> PHP_API_FUNCTION fetch = php_get_api_function(apc_api, "fetch");
>>> >>> fetch(key);
>>> >>>
>>> >>
>>> >> If I understand correctly, it sounds like what you're proposing
>>> (please
>>> >> correct me if I'm wrong about the code above), is that we could avoid
>>> >> including function prototypes and instead treat all API functions as
>>> regular
>>> >> internal PHP functions that are exposed to user space (or some similar
>>> >> structure that avoid explicit declaration of function arguments and
>>> return
>>> >> values, in favor of generic ones)?
>>> >>
>>> >> I think this is possible, however, I would expect two problems with
>>> this
>>> >> approach:
>>> >>
>>> >> - Repeated calls to internal functions will likely be slower due to
>>> the
>>> >> argument handling, validation, etc. We'll also loose performance
>>> simply
>>> >> because you loose the efficiency of passing the parameters as normal C
>>> >> functions.
>>> >>
>>> >> - If these aren't much different than PHP_FE entries, then we could
>>> simply
>>> >> call via user space functions and get the same functionality with
>>> functions
>>> >> like version(), function_exists(), and internally zend_call_function
>>> etc.
>>> >>
>>> >> An argument could be made here of course that an extension wanting
>>> this
>>> >> functionality could simply do the above, but I don't think this offers
>>> the
>>> >> performance requirements that I see some use cases needing. For
>>> example
>>> >> calls that are done repeatedly in a real application such as
>>> serialization,
>>> >> storing data in a caching extension, reading data from a remote server
>>> etc.
>>> >>
>>> >
>>> > Yes, I now get the performance issue with this design and that it's not
>>> > very suitable solution :P.
>>> >
>>> >
>>> >>
>>> >> I would also, as Pierre suggested, invite you to solicit input from
>>> the
>>> >> PECL list in general as this is an idea that hasn't been exposed at
>>> all to
>>> >> many of the other PECL developers and it might be useful to get
>>> further
>>> >> input.
>>> >
>>> >
>>> > I forwarded the two previous mails to the pecl-dev list. I think there
>>> > weren't any replies because it was during the weekend. I'll cc to the
>>> > pecl-dev list and not to the gsoc list here onwards.
>>> >
>>> >>
>>> >> -shire
>>> >
>>> >
>>> > Thank you
>>> > Varuna
>>> >
>>>
>>
>>
>