let me elaborate more on the Title. Consider for example PHP_FUNCTION(session_start). Will I be able to invoke session_start from within session_id which is another PHP_FUNCTION (this is just for illustration not the actual purpose)?
Well, yes, but you should avoid it as much as possible. One of the main benefits of writing internal implementations of functions is that, contrary to what happens in PHP, C function calls are cheap. Additionally, calling PHP functions internally in C code is relatively painful.
For instance, in the case of session_start, you have php_session_start, which is exposed by the session extension. Owing to what I described in the first paragraph, extensions will usually export C functions that may be useful to others.
In fact, the internal PHP function foo needed to call the internal PHP function bar, the best strategy, if possible, would be to define an auxiliary (non PHP_FUNCTION) C function with most of the implementation of bar. Then both PHP_FUNCTION(foo) and PHP_FUNCTION(bar) could call that auxiliary function.
Anyway, the easiest way to call PHP functions is to use call_user_function:
int call_user_function(HashTable *function_table, zval **object_pp,
zval *function_name, zval *retval_ptr, zend_uint param_count,
zval *params[] TSRMLS_DC);
The variant call_user_function_ex also allows prohibiting separation when the argument should be sent by reference by it's not and specifying a symbol table.
This will work both if the relevant function is internal (PHP_FUNCTION) or was defined in userspace. If it's a regular function, you should use EG(function_table) as the first argument, the second should be NULL and I think you can figure out the others.
If you execute the function several times, this is not very efficient. In that case, see the functions in "Zend_API.h" that start with zend_fcall_.
I wouldn't recommend other options to call internal functions, such as manually setting up the arguments stack and other trickery and them manually calling the underlying C function.
ie. session_start(session_id())
Yes, however in this case it doesn't make sense because session_id() requires the session to already be started.
Related
So i'm writing an extension to act as a wrapper for a certain multithreaded networking library. Now, the pattern used is a simple request-reply.
All I want to do is allocate a zend_string (with zend_string_init) for the reply, and return it via return_value. The thing is, I don't want to explicitly call zend_string_release, because of how php treats zvals.
What I mean by that is: if a certain zval gets to php userland, it will be destroyed and freed after it is no longer used. If it doesn't get there (e.g. a user will use in php something like "myfunc();", instead of "$result = myfunc();" ), I have to destroy it.
I find this to be quite a tricky case. I wonder if there isn't some function or macro or field in the execute_data parameter, that can tell me if the result from my function is used in php or not. If it isn't used, then it means that I don't need to alloc memory for the reply. If it is, I will alloc memory and return it, and it will be freed automatically.
EDIT: if such a mechanism doesn't exist or isn't reliable or isn't best practice to use (as another user pointed out), how should memory be managed?
For instance something like
PHP_FUNCTION(myfunc)
{
zend_string *dummy = zend_string_init("dummy", sizeof("dummy") - 1, 0);
RETVAL_STR(dummy);
return;
}
would cause a memory leak if the user doesn't do something like $var = myfunc() in php, and it would also cause a double free if the user does indeed do
$var = myfunc() and I do something like zend_string_release(dummy) in the RSHUTDOWN() function (assuming i have a pointer to it saved somehow in a global hashtable)
In general, you shouldn't have to worry about handling the lifecycle of a function's return value. The PHP engine handles this value just like any other value in userland. In other words, your conception of the return value "being used" (or "not being used") in userland is not quite correct. In fact, every return value is "used" by the engine whether the userland code assigns the return value to a variable or not. This means PHP's automatic memory management is applied and everything is handled and eventually freed properly.
Underneath the hood, every PHP_FUNCTION is passed a zval having the argument name return_value (of course, the PHP_FUNCTION macro hides this fact). This zval is always initialized to NULL (e.g. ZVAL_NULL(return_value)) before the function is even called. The macro RETVAL_STR(str) evaluates into the call ZVAL_STR(return_value,str), which assigns the zend_string* to the existing return_value zval. Keeping in mind that a zend_string is a reference-counted structure, the assigning zval inherits the initial reference set via zend_string_init. The engine will then handle reference-counting the assigned zend_string* and will eventually call zend_string_release once the zend_string's reference counter hits zero (i.e. it is no longer in use by any zvals). The engine handles destroying the return_value zval after potentially assigning the value to another zval via a variable assignment, function call parameter assignment, ETC.
Note: if anyone reading this is more familiar with PHP5 than PHP7 (like myself), then note it is the same concept except the zend_string* is a char*, and in PHP5 the zval itself is reference-counted instead of the zend_string.
So, for example, consider this:
<?php
myfunc();
The return value is handled by the engine in this instance like we'd expect using PHP's reference-counting system. The refcount for the zend_string* peaks at 1 and is decremented once before being destroyed. In other words, the zend_string lives entirely within the return_value zval before getting cleaned up. Now consider this other case:
<?php
$val = myfunc();
echo "Got message: $val\n";
In this case, the return value is still handled in the exact same way using the reference-counting system, albeit for a longer amount of time (i.e. more refcount increments/decrements). The refcount will at least hit 2 when the return value is assigned to $val. When the engine destroys the return_value zval, the refcount will decrement to 1 since the zend_string* is still alive in $val.
I hope this cleared things up. Note that I also answered a very similar question to yours a while back; it may be useful to you as well.
I am trying to identify pure functions in PHP code.
A pure function is one where both these statements about the function hold:
The function always evaluates the same result value given the same argument value(s). The function result value cannot depend on any hidden information or state that may change as program execution proceeds or between different executions of the program, nor can it depend on any external input from I/O devices.
Evaluation of the result does not cause any semantically observable side effect or output, such as mutation of mutable objects or output to I/O devices.
(definition from Wikipedia)
Is it sufficient to say that a PHP function is pure if and only if
all its arguments are passed by value (no & in the argument list)
it does not use object members (no $this in the function body)
it does not use globals (it doesn't contain global in the function body)
it does not use superglobals (it doesn't contain $_ variables)
Are these statements true ?
Am I missing any use cases ?
You are missing a lot of use-cases
rand()
database interaction
file IO
static variables
calls to other functions with global
import/require statements inside functions
functions with internal state like ob_get_contents()
mutating array pointers
There is probably a lot of stuff I'm not thinking of. PHP has a very stateful design.
I will always be in confusion whether to create pass/call by reference functions. It would be great if someone could explain when exactly I should use it and some realistic examples.
A common reason for calling by reference (or pointers) in other languages is to save on space - but PHP is smart enough to implement copy-on-write for arguments which are declared as passed-by-value (copies). There are also some hidden semantic oddities - although PHP5 introduced the practice of always passing objects by reference, array values are always stored as references, call_user_func() always calls by value - never by reference (because it itself is a function - not a construct).
But this is additional to the original question asked.
In general its good practice to always declare your code as passing by value (copy) unless you explicitly want the value to be different after the invoked functionality returns. The reason being that you should know how the invoked functionality changes the state of the code you are currently writing. These concepts are generally referred to as isolation and separation of concerns.
Since PHP 5 there is no real reason to pass values by reference.
One exception is if you want to modify arrays in-place. Take for example the sort function. You can see that the array is passed by reference, which means that the array is sorted in place (no new array is returned).
Or consider a recursive function where each call needs to have access to the same datum (which is often an array too).
In php4 it was used for large variables. If you passed an array in a function the array was copied for use in the function, using a lot of memory and cpu. The solution was this:
function foo(&$arr)
{
echo $arr['value'];
}
$arr = new array();
foo($arr);
This way you only passed the reference, a link to the array and save memory and cpu. Since php5 every object and array (not sure of scalars like int) are passed by reference internally so there isn't any need to do it yourself.
This is best when your function will always return a modified version of the variable that is passed to it to the same variable
$var = modify($var);
function modify($var)
{
return $var.'ret';
}
If you will always return to the passed variable, using reference is great.
Also, when dealing with large variables and especially arrays, it is good to pass by reference wherever feasible. This helps save on memory.
Usually, I pass by reference when dealing with arrays since I usually return to the modified array to the original array.
Target is to have something like:
#define sum( f1, f2 ) ( f1 + f2 )
where
sum(2,2)
is 4 in PHP. Is that somehow possible? Even better would be if I could call:
$s = 'first';
APPEND ' and second';
when append will be defined as function/method/something else which is appending to $s so after those 2 lines $s would be 'first and second'.
The point of macros in C is that they are expanded at compile time.
Therefore, using the macros does not have an impact on the speed of your code, which a function doing the same would have.
Therefore, an example of usage is:
#define MYPRINTF(x) printf("MYPRINTF says : %s\n",x)
MYPRINTF("blah");
The code above will be translated by the compiler directly into:
printf("MYPRINTF says : %s\n","blah");
The whole point of it is that it is faster than defining a function, such as this one:
void myprintf(char *x)
{
printf("myprintf says : %s\n","blah");
}
Because there is no overhead (in a function, you need to push arguments to the stack, etc).
In an interpreted language, like PHP, the above doesn't hold, as everything is executed directly during run-time, therefore using a mechanism like C's #define would be absolutely useless -- therefore, to answer your question, simply use ordinary functions instead.
just a thought from your comments
function withVeryLongWroteByAnIdiot() {
....
}
function xFunc() {
return withVeryLongWroteByAnIdiot();
}
PHP doesn't support macros in this sense, the (really quite valid) argument I believe being that there's not much difference between this and a normal function in PHP.
After all, it's not like there's any value in having a concept like this in a run-time interpreted language.
I don't believe PHP supports macros. If you think about it, macros in C aren't fancy constants, rather constants are the world's most boring C macros. PHP only understands the boring form through the define function.
That said, I disagree with the other respondents about their validity. There is a valid reason for them: when you want to use built-in functions to preprocess something. For example:
macro default_if_empty_value(value, default) (empty(value) ? default : value)
If you try to write that as a function and call it:
default_if_empty_value($this->that['something']->or[$other], 'Not here.');
then you'll get a PHP warning if any part of that variable chain is not defined, and the expanded version is harder to read:
empty($this->that['something']->or[$other]) ? 'Not here.' : $this->that['something']->or[$other];
PHP code is compiled, but it is compiled at runtime. A macro like this would be expanded by the PHP interpreter and then compiled into PHP bytecode. This bytecode is often cached by the PHP interpreter or an add-on like APC.
I have a string that stores some variables that must be executed to produce a result, for example:
define('RUN_THIS', '\$something.",".$somethingElse');
Which is then eval()-uated:
$foo = eval("return ".RUN_THIS.";");
I understand that eval is unsafe if the string that gets evaluated is from user input. However, if for example I wanted to have everything run off Facebook's HipHop which doesn't support eval() I couldn't do this.
Apparently I can use call_user_func() - is this effectively the same result as eval()? How is deemed to be secure when eval() isn't, if that is indeed the case?
Edit:
In response to the comments, I didn't originally make it clear what the goal is. The constant is defined in advance in order that later code, be it inside a class that has access to the configuration constants, or procedural code, can use it in order to evaluate the given string of variables. The variables that need to be evaluated can vary (completely different names, order, formatting) depending on the situation but it's run for the same purpose in the same way, which is why I currently have the string of variables set in a constant in this way. Technically, eval() is not unsafe as long as the config.php that defines the constants is controlled but that wasn't the point of the question.
Kendall seems to have a simple solution, but I'll try to answer your other question:
Apparently I can use call_user_func() - is this effectively the same result as eval()? How is deemed to be secure when eval() isn't, if that is indeed the case?
call_user_func is actually safer than eval because of the fact that call_user_func can only call one user function. eval on the other hand executes the string as PHP code itself. You can append '; (close the string and start a new "line" of code) at the end of the string and then add some more code, add a ;' (end the line of code and start another string so that there is no syntax error), thus allowing the constant RUN_THIS to contain lots of PHP code that the user can run on the server (including deleting all your important files and retrieving information for databases, etc. NEVER LET THIS HAPPEN.
call_user_func doesn't let his happen. When you run call_user_func_array($func, $args) the user can only run a restricted set of functions because: (a) the function has to be user defined (b) you can manipulate $func to ensure the user isn't able to run any function he/she wants either by checking that $func is in a list of "allowed functions" or by prefixing something like user_ to the function names and the $func variable itself (This way the user can run only functions beginning with user_.
I can't see any reason why you can't just use double-quote string building.
$foo = "\$something,$somethingElse";