I am a PHP programmer trying to learn more of the theory behind PHP, but having trouble connecting the dots between PHP and C. For example, is the arrow operator exactly the same in PHP and C?
Here's what I came up when I researched it:
In C, -> is just an alias, a->b is the same as (*a).b. The arrow operator is just dereferencing a pointer so you interact with the address variable.
In PHP, -> is a reference. It "references the attributes of an instantiated object" (Unknown). But is that the same thing as C?
Note: Today, I learned what pointers are in C.
In PHP, -> is used to access members of a class. C does not have classes.
The closest thing is a struct.
In PHP
class Animal {
public $color;
public $age;
}
$fido = new Animal;
$fido->color = 'white';
$fido->age = 3;
$kitty = new Animal;
$kitty->color = 'brown';
$kitty->age = 5;
// output
echo 'Fido is ' . $fido->color . "age=". $fido->age . "\n";
echo 'Kitty is ' . $kitty->color . "age=". $kitty->age . "\n";
Output is:
Fido is white age=3
Kitty is brown age=5
You can do something similar in C using structs. It's a bit more involved.
Excuse my C. It's quite rusty
struct Animal {
int age;
char color[50];
};
int size = sizeof(struct Animal);
struct Animal * fido = malloc(size);
struct Animal * kitty = malloc(size);
fido->age = 3;
strcpy(fido->color, "white");
kitty->age = 5;
strcpy(kitty->color, "brown");
printf("Fido is %s age=%d\n", fido->color, fido->age);
printf("Kitty is %s age=%d\n", kitty->color, fido->age);
Unless you really want to get into the underlying details, don't overthink PHP references. What that means is that they don't pass around the actual values when doing function calls etc.
Don’t try too hard to find equivalence between the two languages. Their semantics are simply too different, so this will fail.
That said, the dereference operator -> in PHP was likely chosen to visually resemble the member access operator -> in C, and the semantics are somewhat similar, in that both allow you to access a member of a dereferenced object.
I’m not sure what you mean by “In C, -> is just an alias”: The C language has a concept of “alias”, but it’s completely unrelated with the topic at hand.
Rather, -> is an operator, and the expression a->b is defined to be equivalen to (*a).b, as you said correctly. But unlike you said, the object doesn’t need to be allocated on the heap, it can be anywhere in memory. Consider the following:
struct foo {
int i;
};
int main(void) {
struct foo f = {42};
struct foo *pf = &f;
printf("f.i = %d\n", pf->i);
}
Here, pf->i is equivalent to f.i (or (*pf).i). In no case is i allocated on the heap.
In php arrow -> is used to access function of a class.
class A{
function funA(){
return "Hello World";
}
}
$object1 = new A();
$object1->funA;
Object will be
Hello World
You can also access nested objects by arrow operator in PHP.
We will convert string to object. Here is my string:
{
"id":"123456",
"msg":"Have a Nice Day",
"is_active":false,
"total_count":1
}
IF i encode it to JSON
$obj = json_decode($json, false);
I can easily get object value by -> operator
$obj->msg;
OutPut will be
Have a Nice Day
You can do similar in C by using structs.
Related
I need to return few values from rust function. Tried to declare function which returns an array
$ffi = FFI::cdef('float get_arr()[2];', './target/release/libphp_rust.dylib');
$array = $ffi->get_arr();
But got an error:
PHP Fatal error: Uncaught FFI\ParserException: function returning array is not allowed at line 1 in /array.php:3
It seems PHP FFI can't work with arrays directly. So I found another solution.
I created C-array from PHP, then passed pointer to it to Rust code and then populated it with Rust function:
$ffi = FFI::cdef('bool get_arr(float (*res)[2]);', './target/release/libphp_rust.dylib');
$array = $ffi->new('float[2]');
$result = $ffi->get_arr(FFI::addr($array));
if ($result) {
var_dump($array);
} else {
//... something went wrong
}
#[no_mangle]
pub extern fn get_arr(array_pointer: *mut [f32;2]) -> bool {
let res = unsafe {
assert!(!array_pointer.is_null());
&mut *array_pointer
};
res[0] = 0.1;
res[1] = 0.2;
return true;
}
This solutions seems to work correct but i have some doubts about it:
Is passing pointers to FFI safe enough and what problems may I face with this in future?
Are Rust arrays fully C-compatible so that I'm able to assign value to it directly by index?
I there better way to achieve what I need? Or maybe are there some good practices about passing complex data structures with FFI?
Thanks
The rules surrounding this are still up in the air, so your example is questionably safe. This should be ok, but requires nightly features:
#![feature(maybe_uninit_extra)]
#![feature(ptr_as_uninit)]
// Make sure you use `extern "C"`. `extern` alone means `extern "Rust"`.
#[no_mangle]
pub extern "C" fn get_arr(array_pointer: *mut [f32; 2]) -> bool {
let fat: *mut [f32] = array_pointer;
let res = unsafe { fat.as_uninit_slice_mut().unwrap() };
res[0].write(0.1);
res[1].write(0.2);
true
}
On the stable channel it's just less elegant:
// Make sure you use `extern "C"`. `extern` alone means `extern "Rust"`.
#[no_mangle]
pub extern "C" fn get_arr(array_pointer: *mut [f32; 2]) -> bool {
assert!(!array_pointer.is_null());
unsafe {
let res = array_pointer as *mut f32;
res.add(0).write(0.1);
res.add(1).write(0.2);
}
true
}
i am trying to warp a C library around a PHP class using PHP's Zend Engine. The constructor function of the class is supposed to take a string and a function pointer. I was able to fetch strings values from the __construct arguments and printing them. However when i fetch the function and try to make it run in the class's constructor. I get a segfault error.
Basically, the end result should like like so:
class TestClass
{
function __construct(callable: $callBack, string: $name);
}
(Naturally, there are other methods in the class, but i had no issue with them).
The C extension looks like so:
PHP_METHOD(TestClass, __construct)
{
zend_string* name;
zend_fcall_info fci;
zend_fcall_info_cache fci_cache;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "fS", &fci, &fci_cache, &name) == FAILURE)
return;
php_printf("name: %s\n", ZSTR_VAL(name));
if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS) {
php_printf("Called");
}
zval* obj = getThis();
test_class_t* intern;
intern = Z_TSTOBJ_P(obj);
php_printf("Constructor\n");
zend_string_release(name);
if (fci.params)
efree(fci.params);
}
Segfault doesn't happen when zend_call_function is commented out.
I am using 7.2.19 and C99.
Is there a way to solve this issue?
Thanks
You have to specify a zval for the return value of the function before you can call it. You also have to specify the number of parameters you want to pass:
zval retval;
fci.retval = &retval;
fci.param_count = 0;
// Use zend_call_function()
zval_ptr_dtor(&retval);
To use parameters you have to allocate an array (stack or heap) of zvals to hold the values you want to pass. A simple example would be like this:
zval args[2];
ZVAL_LONG(&args[0], 1);
ZVAL_LONG(&args[1], 2);
fci.params = args;
fci.param_count = 2;
// Use zend_call_function() here.
zval_ptr_dtor(&args[0]);
zval_ptr_dtor(&args[1]);
In case of heap allocation:
zval *args = emalloc(2 * sizeof(zval));
// Assign, call and dtor as in previous example.
efree(args);
In a previous Using R, how to reference variable variables (or variables variable) a la PHP[post]
I asked a question about something in R analagous to PHP $$ function:
Using R stats, I want to access a variable variable scenario similar to PHP double-dollar-sign technique: http://php.net/manual/en/language.variables.variable.php
Specifically, I am looking for a function in R that is equivalent to $$ in PHP.
The get( response works for strings (characters).
lapply is a way to loop over lists
Or I can loop over and get the values ...
for(name in names(vars))
{
val = vars[[name]];
I still haven't had the $$ function in R answered, although the lapply solved what I needed in the moment.
`$$` <- function
that allows any variable type to be evaluated. That is still the question.
UPDATES
> mlist = list('four'="score", 'seven'="years");
> str = 'mlist$four'
> mlist
$four
[1] "score"
$seven
[1] "years"
> str
[1] "mlist$four"
> get(str)
Error in get(str) : object 'mlist$four' not found
> mlist$four
[1] "score"
Or how about attributes for an object such as mobj#index
UPDATES #2
So let's put specific context on the need. I was hacking the texreg package to build a custom latex output of 24 models of regression for a research paper. I am using plm fixed effects, and the default output of texreg uses dcolumns to center, which I don't like (I prefer r#{}l, so I wanted to write my own template. The purpose for me, to code this, is for me to write extensible code that I can use again and again. I can rebuild my 24 tables across 4 pages in seconds, so if the data change, or if I want to tweak the function, I immediately have a nice answer. The power of abstraction.
As I hacked this, I wanted to get more than the number of observations, but also the number of groups, which can be any user defined index. In my case it is "country" (wait for it, hence, the need for variable variables).
If I do a lookup of the structure, what I want is right there: model$model#index$country which would be nice to simply call as $$('model$model#index$country'); where I can easily build the string using paste. Nope, this is my workaround.
getIndexCount = function(model,key="country")
{
myA = attr(summary(model)$model,"index");
for(i in 1:length(colnames(myA)))
{
if(colnames(myA)[i] == key) {idx = i; break;}
}
if(!is.na(idx))
{
length(unique(myA[,idx]));
} else {
FALSE;
}
}
UPDATES #3
Using R, on the command line, I can type in a string and it gets evaluated. Why can't that internal function be directly accessed, and the element captured that then gets printed to the screen?
There is no equivalent function in R. get() works for all types, not just strings.
Here is what I came up with, after chatting with the R-bug group, and getting some ideas from them. KUDOS!
`$$` <- function(str)
{
E = unlist( strsplit(as.character(str),"[#]") );
k = length(E);
if(k==1)
{
eval(parse(text=str));
} else {
# k = 2
nstr = paste("attributes(",E[1],")",sep="");
nstr = paste(nstr,'$',E[2],sep="");
if(k>2) {
for(i in 3:k)
{
nstr = paste("attributes(",nstr,")",sep="");
nstr = paste(nstr,'$',E[i],sep="");
}
}
`$$`(nstr);
}
}
Below are some example use cases, where I can directly access what the str(obj) is providing... Extending the utility of the '$' operator by also allowing '#' for attributes.
model = list("four" = "score", "seven"="years");
str = 'model$four';
result = `$$`(str);
print(result);
matrix = matrix(rnorm(1000), ncol=25);
str='matrix[1:5,8:10]';
result = `$$`(str);
print(result);
## Annette Dobson (1990) "An Introduction to Generalized Linear Models".
## Page 9: Plant Weight Data.
ctl <- c(4.17,5.58,5.18,6.11,4.50,4.61,5.17,4.53,5.33,5.14);
trt <- c(4.81,4.17,4.41,3.59,5.87,3.83,6.03,4.89,4.32,4.69);
group <- gl(2, 10, 20, labels = c("Ctl","Trt"));
weight <- c(ctl, trt);
lm.D9 <- lm(weight ~ group);
lm.D90 <- lm(weight ~ group - 1); # omitting intercept
myA = anova(lm.D9); myA; str(myA);
str = 'myA#heading';
result = `$$`(str);
print(result);
myS = summary(lm.D90); myS; str(myS);
str = 'myS$terms#factors';
result = `$$`(str);
print(result);
str = 'myS$terms#factors#dimnames';
result = `$$`(str);
print(result);
str = 'myS$terms#dataClasses#names';
result = `$$`(str);
print(result);
After realizing the back-tick can be a bit tedious, I chose to update the function, calling it access
access <- function(str)
{
E = unlist( strsplit(as.character(str),"[#]") );
k = length(E);
if(k==1)
{
eval(parse(text=str));
} else {
# k = 2
nstr = paste("attributes(",E[1],")",sep="");
nstr = paste(nstr,'$',E[2],sep="");
if(k>2) {
for(i in 3:k)
{
nstr = paste("attributes(",nstr,")",sep="");
nstr = paste(nstr,'$',E[i],sep="");
}
}
access(nstr);
}
}
i've written this code to test the size of some objects in PHP
<?php
class MyClass
{
public $string1="first string";
public $string2="second string";
public $string3="third string";
public function __toString() {
return $this->string;
}
}
function mem() {
return memory_get_usage(false);
}
$before = mem();
$class = new MyClass;
var_dump("new object size: ".(mem() -$before));
$before=mem();
$string = "test";
var_dump("string size: ".(mem() -$before));
$before=mem();
$objcopy = $class;
var_dump("object copy size: ".(mem() -$before));
$before=mem();
$objref = &$class;
var_dump("object reference size: ".(mem() -$before));
and this is the output in my system:
string(20) "new object size: 188"
string(15) "string size: 80"
string(20) "object copy size: 44"
string(25) "object reference size: 72"
i'm quite confusing now, why do we have: $class>$string>$objref>$objcopy
shouldn't be instead : $class=$objcopy>$string>$objref ?
$objcopy in fact contains 3 strings inside, instead $string is a single one..
could someone explain me how php handle memory with this kind of object?
thanks in advance.
You're observations base on wrong assumptions.
First of all, your $objcopy is a reference to the same instance as $class, because Instances are not cloned when assigning them to another variable. Check the manual or add this to your code:
$objcopy->string1 = 'a';
echo $class->string1, "\n";
Second, even if the assignment operator would effectively make them point to different objects, PHP would probably not allocate new memory because it uses copy-on-write optimization, see http://php.net/manual/en/internals2.variables.intro.php.
Finally, you can't expect precise memory informations returned by PHP. It may allocate more than the current statement requires and may implicitly free memory by the garbage collector. (Well, at least you can turn that off.)
Yes my question was based on wrong knowledge derived by C++ and other languages reference point of view.
So , after long research , i've created a post on my blog about this argument where i explain in depth how php handle memory.
http://hyperweb2.com/home/blog/2013/10/11/php-reference-vs-copy-vs-clone/
I'm working over some php library. I want to track the changes in the interfaces of classes library.
Yes, i'm using GIT. But diff produces more information than i need.
I was trying to compare two versions with phpDocumentor.
phpdoc project:parse -d folder
produce xml file with structure of project interface. I can compare this xml file with another. But these contain more information than I want. Like line numbers, file hash and so on.
So, I want to compare two commits, branches or even forks and find out differences of their interfaces.
Example to compare: http://pastebin.com/1H61dJBT
It also important to know when to change Major version.
MAJOR version when you make incompatible API changes...
http://semver.org/spec/v2.0.0.html
I reckon you want to build a workflow around PHP Smart Differencer
An example of the PHP Smart Differencer's results can be seen here. This page contains an example of the output generated by SD's PHP Smart Differencer tool
when applied to an original file and an updated version of the same file.
If you really want to roll your own, you might build it around PHP-Parser which will likely give you a bit more precision, but you would need to generate your own comparison algorithms where SmartDifferencer's tool already has that built in.
Either of these will give you what it seems you are looking for.
Plain diff reports differences in terms of text lines. Software is defined in terms of code structures. The mismatch between source-code-as-text-lines and source as structures is what make diff's output hard to understand.
You could instead compare the interface definitions with Semantic Designs (my company's) SmartDifferencer.
This reports the minimal edits on code structures (not lines) to convert one piece of (PHP) code into another. Changes to names of interface functions, inserted or deleted parameters, become pretty obvious. Line breaks aren't relevant and don't influence SmartDifferencer's results; neither are comments unless you insist they are. (SmartDifferencer isn't limited to PHP; there's versions for many languages).
EDIT: OP wanted to know what SmartDifferencer did on a specific example of an interface change (before and after PHP files). What follows are his two sample files, their SmartDifferencer output, and Unix-diff output. I remark there's a lot of changes in these pretty small example files.
First interface:
<?php
// ----- first version -----
namespace vendor\package;
class someClass
{
private $c;
public function __construct($a, $b)
{
$c = $a + $b;
}
/**
* #return string
*/
public function returnC()
{
return $this->c;
}
public function saySomething()
{
echo 'something';
}
}
Modified interface file
<?php
// ----- second version -----
namespace vendor\package;
class someClass
{
private $a, $b;
public function __construct($a, $b)
{
$this->a = $a;
$this->b = $b;
}
public function saySomething($something = 'something')
{
echo $something;
}
/**
* #return integer
*/
public function returnC()
{
return $this->a + $this->b;
}
}
Smart Differencer output (M.N means "Line M, column N"):
C:>DMSSmartDifferencer PHP~PHP5 \temp\first_version.php \temp\second_version.php
Copyright (C) 2009-2012 Semantic Designs; All Rights Reserved
PHP~PHP5 SmartDifferencer Version 1.0.14
Copyright (C) 2012 Semantic Designs, Inc; All Rights Reserved; SD Confidential
Powered by DMS (R) Software Reengineering Toolkit
*** Unregistered SmartDifferencer Version 1.0
*** Operating with evaluation limits.
*** Parsing file C:/temp/first_version.php ...
*** Parsing file C:/temp/second_version.php ...
*** Creating suffix tree ...
*** Determining maximal pairs ...
*** Sorting maximal pairs ...
*** Determining differences ...
*** Printing edits ...
Substitute 7.13-7.14 by 7.13-7.18
< $c
> $a, $b
Substitute 10.9-10.21 by 11.9-12.22
< $c = $a + $b;
> $this->a = $a;
> $this->b = $b;
At 15.12 insert 15.12-18.9 moving 19.21-19.32 to 15.21-15.32
> function saySomething($something = 'something')
> {
> echo $something;
> }
Delete 15.12-18.9 at 15.12 moving 15.21-15.27 to 23.21-23.27
< function returnC()
< {
< return $this->c;
< }
At 19.21 insert 23.21-23.27 moving 15.21-15.27 to 23.21-23.27
> returnC
Delete 19.21-19.32 at 23.21 moving 19.21-19.32 to 15.21-15.32
< saySomething
Substitute 21.9-21.25 by 25.9-25.35
< echo 'something';
> return $this->a + $this->b;
Exiting with final status 1.
You should see that SmartDifferencer is focused on the deltas in the code structure,
not deltas in the lines. The first thing you notice is that SmartDifferencer completely ignored the comments, as they have no impact on what the code does.
But the most glaring example of this in the unix diff below is the multiple diffs that lump a delta at the end of one function with a delta at beginning of another; no programmer explains differences in code that way. Such a confused diff makes for confusing reading when trying to understand what really changed.
Output from unix-style diff:
C:>diff \temp\first_version.php \temp\second_version.php
2c2
< // ----- first version -----
---
> // ----- second version -----
7c7,8
< private $c;
---
> private $a, $b;
>
10c11,17
< $c = $a + $b;
---
> $this->a = $a;
> $this->b = $b;
> }
>
> public function saySomething($something = 'something')
> {
> echo $something;
11a19
>
13c21
< * #return string
---
> * #return integer
17,21c25
< return $this->c;
< }
< public function saySomething()
< {
< echo 'something';
---
> return $this->a + $this->b;
22a27
>
What neither SmartDifferencer nor diff do, is tell you that the behavior of an interface changed, because the code on which it depends changed. The only way to do that is a static semantic analysis of all code directly or indirectly supporting the interface, and that's a lot harder problem.