Arg info / zpp mismatch on PHP 8.0

php.internals

James Colannino

5 years ago
I have the following method defined in a PHP 8 extension: ZEND_BEGIN_ARG_INFO(arginfoCtor, 0)     ZEND_ARG_TYPE_INFO(0, hostname, IS_STRING, 0)     ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 1) ZEND_END_ARG_INFO() PHP_METHOD(Trogdord, __construct) {     trogdordObject *objWrapper = ZOBJ_TO_TROGDORD(Z_OBJ_P(getThis()));     char *hostname;     size_t hostnameLength;     long port = TROGDORD_DEFAULT_PORT;     zend_parse_parameters_throw(         ZEND_NUM_ARGS(),         "s|l",         &hostname,         &hostnameLength,         &port     );     ... } This works fine on PHP 7, but on PHP 8, I get an "Arg info / zpp mismatch" error. I discovered that if I comment out "ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 1)", it works, but I'd like to type hint that second optional argument if possible. Maybe I was always doing this the wrong way, but I thought that the last argument 1 to allow null was the proper way to handle this and I'm not sure why it results in an error now. Can anyone tell me the correct way to approach this in PHP 8? Thank you!

Nikita Popov

5 years ago
On Fri, Jan 15, 2021 at 6:11 PM James Colannino <composer@colannino.dev> wrote:
> I have the following method defined in a PHP 8 extension: > > ZEND_BEGIN_ARG_INFO(arginfoCtor, 0) > ZEND_ARG_TYPE_INFO(0, hostname, IS_STRING, 0) > ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 1) > ZEND_END_ARG_INFO() > > PHP_METHOD(Trogdord, __construct) { > > trogdordObject *objWrapper = ZOBJ_TO_TROGDORD(Z_OBJ_P(getThis())); > > char *hostname; > size_t hostnameLength; > long port = TROGDORD_DEFAULT_PORT; > > zend_parse_parameters_throw( > ZEND_NUM_ARGS(), > "s|l", > &hostname, > &hostnameLength, > &port > ); > > ... > } > > This works fine on PHP 7, but on PHP 8, I get an "Arg info / zpp > mismatch" error. I discovered that if I comment out > "ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 1)", it works, but I'd like to > type hint that second optional argument if possible. Maybe I was always > doing this the wrong way, but I thought that the last argument 1 to > allow null was the proper way to handle this and I'm not sure why it > results in an error now. > > Can anyone tell me the correct way to approach this in PHP 8? Thank you! >
Your arginfo declares the arugment as nullable, but your zpp call does not. Thus the error. You need: zend_bool port_is_null = 1; zend_parse_parameters_throw( ZEND_NUM_ARGS(), "s|l!", // ! means nullable &hostname, &hostnameLength, &port, &port_is_null // Whether null was actually passed ); Regards, Nikita

James Colannino

5 years ago
On 1/15/21 9:15 AM, Nikita Popov wrote:
> On Fri, Jan 15, 2021 at 6:11 PM James Colannino <composer@colannino.dev> > wrote: > >> I have the following method defined in a PHP 8 extension: >> >> ZEND_BEGIN_ARG_INFO(arginfoCtor, 0) >> ZEND_ARG_TYPE_INFO(0, hostname, IS_STRING, 0) >> ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 1) >> ZEND_END_ARG_INFO() >> >> PHP_METHOD(Trogdord, __construct) { >> >> trogdordObject *objWrapper = ZOBJ_TO_TROGDORD(Z_OBJ_P(getThis())); >> >> char *hostname; >> size_t hostnameLength; >> long port = TROGDORD_DEFAULT_PORT; >> >> zend_parse_parameters_throw( >> ZEND_NUM_ARGS(), >> "s|l", >> &hostname, >> &hostnameLength, >> &port >> ); >> >> ... >> } >> >> This works fine on PHP 7, but on PHP 8, I get an "Arg info / zpp >> mismatch" error. I discovered that if I comment out >> "ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 1)", it works, but I'd like to >> type hint that second optional argument if possible. Maybe I was always >> doing this the wrong way, but I thought that the last argument 1 to >> allow null was the proper way to handle this and I'm not sure why it >> results in an error now. >> >> Can anyone tell me the correct way to approach this in PHP 8? Thank you! >> > Your arginfo declares the arugment as nullable, but your zpp call does not. > Thus the error. You need: > > zend_bool port_is_null = 1; > zend_parse_parameters_throw( > ZEND_NUM_ARGS(), > "s|l!", // ! means nullable > &hostname, > &hostnameLength, > &port, > &port_is_null // Whether null was actually passed > );
I tried that, but I still get the "Arginfo / zpp mismatch during call" error.

James Colannino

5 years ago
On 1/15/21 9:20 AM, James Colannino wrote:
> > On 1/15/21 9:15 AM, Nikita Popov wrote: >> On Fri, Jan 15, 2021 at 6:11 PM James Colannino <composer@colannino.dev> >> wrote: >> >>> I have the following method defined in a PHP 8 extension: >>> >>> ZEND_BEGIN_ARG_INFO(arginfoCtor, 0) >>>       ZEND_ARG_TYPE_INFO(0, hostname, IS_STRING, 0) >>>       ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 1) >>> ZEND_END_ARG_INFO() >>> >>> PHP_METHOD(Trogdord, __construct) { >>> >>>       trogdordObject *objWrapper = >>> ZOBJ_TO_TROGDORD(Z_OBJ_P(getThis())); >>> >>>       char *hostname; >>>       size_t hostnameLength; >>>       long port = TROGDORD_DEFAULT_PORT; >>> >>>       zend_parse_parameters_throw( >>>           ZEND_NUM_ARGS(), >>>           "s|l", >>>           &hostname, >>>           &hostnameLength, >>>           &port >>>       ); >>> >>>       ... >>> } >>> >>> This works fine on PHP 7, but on PHP 8, I get an "Arg info / zpp >>> mismatch" error. I discovered that if I comment out >>> "ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 1)", it works, but I'd like to >>> type hint that second optional argument if possible. Maybe I was always >>> doing this the wrong way, but I thought that the last argument 1 to >>> allow null was the proper way to handle this and I'm not sure why it >>> results in an error now. >>> >>> Can anyone tell me the correct way to approach this in PHP 8? Thank >>> you! >>> >> Your arginfo declares the arugment as nullable, but your zpp call >> does not. >> Thus the error. You need: >> >>       zend_bool port_is_null = 1; >>       zend_parse_parameters_throw( >>           ZEND_NUM_ARGS(), >>           "s|l!", // ! means nullable >>           &hostname, >>           &hostnameLength, >>           &port, >>           &port_is_null // Whether null was actually passed >>       ); > > > I tried that, but I still get the "Arginfo / zpp mismatch during call" > error.
This is the code I have now, which is still giving me the error on PHP 8: ZEND_BEGIN_ARG_INFO(arginfoCtor, 0)     ZEND_ARG_TYPE_INFO(0, hostname, IS_STRING, 0)     ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 1) ZEND_END_ARG_INFO() PHP_METHOD(Trogdord, __construct) {     trogdordObject *objWrapper = ZOBJ_TO_TROGDORD(Z_OBJ_P(getThis()));     char *hostname;     size_t hostnameLength;     long port = TROGDORD_DEFAULT_PORT;     zend_bool portIsNull = 1;     zend_parse_parameters_throw(         ZEND_NUM_ARGS(),         "s|l!",         &hostname,         &hostnameLength,         &port,         &portIsNull     );     ... }

Christoph Becker

5 years ago
On 15.01.2021 at 18:40, James Colannino wrote:
> On 1/15/21 9:20 AM, James Colannino wrote: >> >> On 1/15/21 9:15 AM, Nikita Popov wrote: >>> On Fri, Jan 15, 2021 at 6:11 PM James Colannino <composer@colannino.dev> >>> wrote: >>> >>>> I have the following method defined in a PHP 8 extension: >>>> >>>> ZEND_BEGIN_ARG_INFO(arginfoCtor, 0) >>>>       ZEND_ARG_TYPE_INFO(0, hostname, IS_STRING, 0) >>>>       ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 1) >>>> ZEND_END_ARG_INFO() >>>> >>>> PHP_METHOD(Trogdord, __construct) { >>>> >>>>       trogdordObject *objWrapper = >>>> ZOBJ_TO_TROGDORD(Z_OBJ_P(getThis())); >>>> >>>>       char *hostname; >>>>       size_t hostnameLength; >>>>       long port = TROGDORD_DEFAULT_PORT; >>>> >>>>       zend_parse_parameters_throw( >>>>           ZEND_NUM_ARGS(), >>>>           "s|l", >>>>           &hostname, >>>>           &hostnameLength, >>>>           &port >>>>       ); >>>> >>>>       ... >>>> } >>>> >>>> This works fine on PHP 7, but on PHP 8, I get an "Arg info / zpp >>>> mismatch" error. I discovered that if I comment out >>>> "ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 1)", it works, but I'd like to >>>> type hint that second optional argument if possible. Maybe I was always >>>> doing this the wrong way, but I thought that the last argument 1 to >>>> allow null was the proper way to handle this and I'm not sure why it >>>> results in an error now. >>>> >>>> Can anyone tell me the correct way to approach this in PHP 8? Thank >>>> you! >>>> >>> Your arginfo declares the arugment as nullable, but your zpp call >>> does not. >>> Thus the error. You need: >>> >>>       zend_bool port_is_null = 1; >>>       zend_parse_parameters_throw( >>>           ZEND_NUM_ARGS(), >>>           "s|l!", // ! means nullable >>>           &hostname, >>>           &hostnameLength, >>>           &port, >>>           &port_is_null // Whether null was actually passed >>>       ); >> >> >> I tried that, but I still get the "Arginfo / zpp mismatch during call" >> error. > > > This is the code I have now, which is still giving me the error on PHP 8: > > ZEND_BEGIN_ARG_INFO(arginfoCtor, 0)
You need to tell arginfo about the optional parameter: ZEND_BEGIN_ARG_INFO_EX(arginfoCtor, 0, 0, 1) However, it is much simpler to write a stub file, and to let build/gen_stub.php generate the arginfo for you. See e.g. <https://github.com/php/php-src/blob/master/ext/standard/basic_functions.stub.php>.

James Colannino

5 years ago
On 1/15/21 10:17 AM, Christoph M. Becker wrote:
> On 15.01.2021 at 18:40, James Colannino wrote: > >> On 1/15/21 9:20 AM, James Colannino wrote: >>> On 1/15/21 9:15 AM, Nikita Popov wrote: >>>> On Fri, Jan 15, 2021 at 6:11 PM James Colannino <composer@colannino.dev> >>>> wrote: >>>> >>>>> I have the following method defined in a PHP 8 extension: >>>>> >>>>> ZEND_BEGIN_ARG_INFO(arginfoCtor, 0) >>>>>       ZEND_ARG_TYPE_INFO(0, hostname, IS_STRING, 0) >>>>>       ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 1) >>>>> ZEND_END_ARG_INFO() >>>>> >>>>> PHP_METHOD(Trogdord, __construct) { >>>>> >>>>>       trogdordObject *objWrapper = >>>>> ZOBJ_TO_TROGDORD(Z_OBJ_P(getThis())); >>>>> >>>>>       char *hostname; >>>>>       size_t hostnameLength; >>>>>       long port = TROGDORD_DEFAULT_PORT; >>>>> >>>>>       zend_parse_parameters_throw( >>>>>           ZEND_NUM_ARGS(), >>>>>           "s|l", >>>>>           &hostname, >>>>>           &hostnameLength, >>>>>           &port >>>>>       ); >>>>> >>>>>       ... >>>>> } >>>>> >>>>> This works fine on PHP 7, but on PHP 8, I get an "Arg info / zpp >>>>> mismatch" error. I discovered that if I comment out >>>>> "ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 1)", it works, but I'd like to >>>>> type hint that second optional argument if possible. Maybe I was always >>>>> doing this the wrong way, but I thought that the last argument 1 to >>>>> allow null was the proper way to handle this and I'm not sure why it >>>>> results in an error now. >>>>> >>>>> Can anyone tell me the correct way to approach this in PHP 8? Thank >>>>> you! >>>>> >>>> Your arginfo declares the arugment as nullable, but your zpp call >>>> does not. >>>> Thus the error. You need: >>>> >>>>       zend_bool port_is_null = 1; >>>>       zend_parse_parameters_throw( >>>>           ZEND_NUM_ARGS(), >>>>           "s|l!", // ! means nullable >>>>           &hostname, >>>>           &hostnameLength, >>>>           &port, >>>>           &port_is_null // Whether null was actually passed >>>>       ); >>> >>> I tried that, but I still get the "Arginfo / zpp mismatch during call" >>> error. >> >> This is the code I have now, which is still giving me the error on PHP 8: >> >> ZEND_BEGIN_ARG_INFO(arginfoCtor, 0) > You need to tell arginfo about the optional parameter: > > ZEND_BEGIN_ARG_INFO_EX(arginfoCtor, 0, 0, 1) > > However, it is much simpler to write a stub file, and to let > build/gen_stub.php generate the arginfo for you. See e.g. > <https://github.com/php/php-src/blob/master/ext/standard/basic_functions.stub.php>. > >>     ZEND_ARG_TYPE_INFO(0, hostname, IS_STRING, 0) >>     ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 1) >> ZEND_END_ARG_INFO() >> >> PHP_METHOD(Trogdord, __construct) { >> >>     trogdordObject *objWrapper = ZOBJ_TO_TROGDORD(Z_OBJ_P(getThis())); >> >>     char *hostname; >>     size_t hostnameLength; >> >>     long port = TROGDORD_DEFAULT_PORT; >>     zend_bool portIsNull = 1; >> >>     zend_parse_parameters_throw( >>         ZEND_NUM_ARGS(), >>         "s|l!", >>         &hostname, >>         &hostnameLength, >>         &port, >>         &portIsNull >>     ); >> >>     ... >> }
Ahh, okay. That fixed it. Also, I didn't know about build/gen_stub.php. That will help me out a lot in the future. Thank you!