Answering my own question/observation, the following workarounds allow
use of char* name="myclass"; and overbuffered char name[100] = "myclass";
both of which fail normally since INIT_CLASS_ENTRY uses sizeof()
not strlen()
// for various char* or string params
char* phpclassname = "myclass";
char phpclassname[100] = "myclass"; // or as passed in by
string sphpname("myclass");
// deliberately ignore the name for this macro, which depends on sizeof
INIT_CLASS_ENTRY(ce, "", minicooper_class_functions);
// set the name manually afterwards
// char* based
ce.name = strdup(phpclassname);
ce.name_length = strlen(phpclassname);
// or
// string based
ce.name = strdup(sphpname.c_str());
ce.name_length = sphpname.length();
// in fact, since ce.name = strdup() is precisely what the macro does,
// only the length needs to be appropriately set with strlen or .length()
---------- Forwarded Message ----------
Subject: INFO: INIT_CLASS_ENTRY fails on various char entry formats
Date: Monday 13 March 2006 01:46
From: an.dromeda@btconnect.com
To: internals@lists.php.net
I was surprised to find that my class entry failed when I tried to pass the
class name as a parameter. Two common styles (char *myclassname = "myclass";
and (over-buffered) char myclassname[100] = "myclass";) both fail with
INIT_CLASS_ENTRY for a reason that becomes apparent when you look
at the source (interesting experience, having the source available!).
INIT_CLASS_ENTRY determines the classname length by sizeof(myclassname)
not strlen(myclassname), so the former char* returns 4, being the size of a
pointer, and the latter returns 100, being the size of the buffer, neither
being then intended reasonable size of the name as would have been determined
by strlen, here 7 ("myclass").
Consequently, a call to instantiate 'new myclass()' fails, with no such class
name registered.
Maybe that's 'obvious' and I should have known better, but both buffers and
static (?) strings I thought were 'reasonable' and in normal use, so I
thought I'd flag the issue.
(Interestingly, in zend_API.c, ZEND_API int zend_disable_class(char
class_name, uint class_name_length TSRMLS_DC) receives a char for
class_name which it passes to INIT_CLASS_ENTRY, presumably without
ill-effect, and despite the issue above...)
Am I missing something, or is that simply a behaviour that's a) intentional,
or b) understood and just needs to be worked around.
Conundrum: I had assumed that to resolve this, I may need to set up an
'emalloc()' of the precise length required, but in fact this still does not
resolve the issue, as the char* returned by the emalloc will be sizeof()
= 4,
whatever the string.
Is there no way therefore to pass a variable length classname to a dynamic
class creation routine? Seems a little unlikely, but I can't see it in light
of the above.
Guess I can ignore the INIT_CLASS_ENTRY macro, or let it run and then
post-assign the classname with appropriate length based on strlen()
or
std::string.length().
Just a thought.
// Various formats tried:
// char phpclassname[50] = "minicooper";
// char *phpclassname = "minicooper";
char phpclassname[11] = "minicooper"; // this works - exact + 1 for zero
// char phpclassname[10] = "minicooper"; // this fails - insufficient
bytes (to include terminating zero)
// char phpclassname[12] = "minicooper"; // this fails - sizeof is 'too
big' (one spare byte - buffer must be 'exact'
// char phpclassname[50] = "minicooper"; // this fails - ditto - too big
// phpclassname[10] = '\0'; // this does not resolve 'too big' buffers
// string spcname("minicooper"); // this does not work
// Calls based on the above, as appropriate
// INIT_CLASS_ENTRY(ce, spcname.c_str(), minicooper_class_functions);
INIT_CLASS_ENTRY(ce, phpclassname, minicooper_class_functions);
// INIT_CLASS_ENTRY(ce, "minicooper", minicooper_class_functions);
Hello,
that's by design, we don't want to use strlen on ever execution. Instead the
macro use sizeof()
which is done at compile time. The workaround would be to
set the string lentgh after using the macro which works pretty well.
Sidenote, you should be using 'const char* var = "string";' or even better
'const char var[] = "string";' anyway.
regards
marcus
Monday, March 13, 2006, 3:00:57 AM, you wrote:
Answering my own question/observation, the following workarounds allow
use of char* name="myclass"; and overbuffered char name[100] = "myclass";
both of which fail normally since INIT_CLASS_ENTRY usessizeof()
notstrlen()
// for various char* or string params
char* phpclassname = "myclass";
char phpclassname[100] = "myclass"; // or as passed in by
string sphpname("myclass");
// deliberately ignore the name for this macro, which depends on sizeof
INIT_CLASS_ENTRY(ce, "", minicooper_class_functions);
// set the name manually afterwards
// char* based
ce.name = strdup(phpclassname);
ce.name_length = strlen(phpclassname);
// or
// string based ce.name = strdup(sphpname.c_str()); ce.name_length = sphpname.length();
// in fact, since ce.name = strdup() is precisely what the macro does,
// only the length needs to be appropriately set with strlen or .length()
---------- Forwarded Message ----------
Subject: INFO: INIT_CLASS_ENTRY fails on various char entry formats
Date: Monday 13 March 2006 01:46
From: an.dromeda@btconnect.com
To: internals@lists.php.net
I was surprised to find that my class entry failed when I tried to pass the
class name as a parameter. Two common styles (char *myclassname = "myclass";
and (over-buffered) char myclassname[100] = "myclass";) both fail with
INIT_CLASS_ENTRY for a reason that becomes apparent when you look
at the source (interesting experience, having the source available!).
INIT_CLASS_ENTRY determines the classname length by sizeof(myclassname)
not strlen(myclassname), so the former char* returns 4, being the size of a
pointer, and the latter returns 100, being the size of the buffer, neither
being then intended reasonable size of the name as would have been determined
by strlen, here 7 ("myclass").
Consequently, a call to instantiate 'new myclass()' fails, with no such class
name registered.
Maybe that's 'obvious' and I should have known better, but both buffers and
static (?) strings I thought were 'reasonable' and in normal use, so I
thought I'd flag the issue.
(Interestingly, in zend_API.c, ZEND_API int zend_disable_class(char
class_name, uint class_name_length TSRMLS_DC) receives a char for
class_name which it passes to INIT_CLASS_ENTRY, presumably without
ill-effect, and despite the issue above...)
Am I missing something, or is that simply a behaviour that's a) intentional,
or b) understood and just needs to be worked around.
Conundrum: I had assumed that to resolve this, I may need to set up an
'emalloc()' of the precise length required, but in fact this still does not
resolve the issue, as the char* returned by the emalloc will besizeof()
= 4,
whatever the string.
Is there no way therefore to pass a variable length classname to a dynamic
class creation routine? Seems a little unlikely, but I can't see it in light
of the above.
Guess I can ignore the INIT_CLASS_ENTRY macro, or let it run and then
post-assign the classname with appropriate length based onstrlen()
or
std::string.length().
Just a thought.
// Various formats tried:
// char phpclassname[50] = "minicooper";
// char *phpclassname = "minicooper";
char phpclassname[11] = "minicooper"; // this works - exact + 1 for zero
// char phpclassname[10] = "minicooper"; // this fails - insufficient
bytes (to include terminating zero)
// char phpclassname[12] = "minicooper"; // this fails - sizeof is 'too
big' (one spare byte - buffer must be 'exact'
// char phpclassname[50] = "minicooper"; // this fails - ditto - too big
// phpclassname[10] = '\0'; // this does not resolve 'too big' buffers
// string spcname("minicooper"); // this does not work
// Calls based on the above, as appropriate // INIT_CLASS_ENTRY(ce, spcname.c_str(), minicooper_class_functions); INIT_CLASS_ENTRY(ce, phpclassname, minicooper_class_functions); // INIT_CLASS_ENTRY(ce, "minicooper", minicooper_class_functions);
Best regards,
Marcus