I need to execute a C program from a PHP script - php

Ok i wanted to create a crawler with my PHP script. Certain parts of my crawler requires real fast manipulation of strings thats why i have decided to use a C/C++ program to assist my PHP script for that particular job. The following is my code:
$op=exec('main $a $b');
echo $op;
main is the executable file generated using my C file main.c i.e main.exe. in the above operation i just made a simple C program which accepts 2 values from PHP and returns the sum of the two values. the following is how my C program in looking like
#include< stdio.h >
#include< stdlib.h >
int main(int argc, char *argv[])
{
int i=add(atoi(argv[1]),atoi(argv[2]));
printf("%d\n",i);
return 0;
}
int add(int a, int b)
{
int c;
c=a+b;
return c;
}
i tried to execute the program via the CMD main 1 1 and it returned 2....it worked! when i entered them in the php script like this,
$a=1;
$b=1;
$op=exec('main $a $b');
echo $op;
it didn't work as expected so any ideas, suggestions or anything else i need to do on my code. I would be great if you could show me an example. THANKS IN ADVANCE!!!

You should enclosed the arguments of exec with double quotes since you're passing variables. And the output of your program is in the second argument of exec.
exec("main $a $b", $out);
print_r($out);
See exec() reference.

The function atoi() cannot distinguish invalid and valid inputs.
I suggest you use strtol() instead.
#include <stdio.h>
#include <stdlib.h>
void quit(const char *msg) {
if (msg) fprintf(stderr, "%s\n", msg);
exit(EXIT_FAILURE);
}
int add(int, int);
int main(int argc, char *argv[]) {
int a, b, i;
char *err;
if (argc != 3) quit("wrong parameter count");
a = strtol(argv[1], &err, 10);
if (*err) quit("invalid first argument");
b = strtol(argv[2], &err, 10);
if (*err) quit("invalid second argument");
i = add(a, b);
printf("%d\n", i);
return 0;
}
int add(int a, int b) {
return a + b;
}

You need to create an executable ./main.
And then use this code.It works
<?php
$a=1;
$b=1;
echo exec("./main $a $b");
?>

Related

Need to rewrite C++ code to PHP

I have a task. I need to rewrite C++ code to PHP.
#include <iostream>
using namespace std;
struct Structure {
int x;
};
void f(Structure st, Structure& r_st, int a[], int n) {
st.x++;
r_st.x++;
a[0]++;
n++;
}
int main(int argc, const char * argv[]) {
Structure ss0 = {0};
Structure ss1 = {1};
int ia[] = {0};
int m = 0;
f(ss0, ss1, ia, m);
cout << ss0.x << " "
<< ss1.x << " "
<< ia[0] << " "
<< m << endl;
return 0;
}
return of a compiler is 0 2 1 0. I have rewrote this code in PHP like this:
<?php
class Structure {
public function __construct($x) {
$this->x = $x;
}
public $x;
}
function f($st, $r_st, $a, $n) {
$st->x++;
$r_st->x++;
$a[0]++;
$n++;
}
$ss0 = new Structure(0);
$ss1 = new Structure(1);
$ia = [0];
$m = 0;
f($ss0, $ss1, $ia, $m);
echo $ss0->x . " "
. $ss1->x . " "
. $ia[0] . " "
. $m . "\n";
return of this code is: 1 2 0 0. I know PHP and I know why it is returning this values. I need to understand how in C++ struct works and why a[0]++ is globally incremented. Please help to rewrite this code on PHP. I also know than there is no struct in PHP.
Difference between:
function f($st, $r_st, $a, $n)
void f(Structure st, Structure& r_st, int a[], int n)
in C++ you always specify, pass by value or by reference, but in PHP there are some pre-defined rules.
Fix for 1st output
C++ part: st is passed by value, and original value, which you pass here is not changed. r_st is passed by reference, and original value is changed.
PHP part: both arguments are passed by reference, since they are classes.
Simple fix there is to clone object st and pass it to function to mimic C++ pass-by-copy, or clone it inside function.
Fix for 3rd output
in C++ int a[] is passed as pointer, so, original value is changed, but in PHP it is passed by value, and it is unchanged outside.
Simple fix for it would be &$a instead of $a in function parameters.
PS. I'm C++ developer, so, PHP part can be inaccurate in terminology.
The ss0 and ss1 variables you are passing in are by object accessors to that function. See Objects and references
The variables passed in are by value. See Passing by Reference
Please help to rewrite this code on PHP.
Do it like this
function f($st, $r_st, &$a, $n) {
$st= clone $st; #clone to get a real copy, not a refer
$st->x++;
$r_st->x++;
$a[0]++; #&$a to simulate ia[] (use as reference)
$n++;
}
Read about references in PHP. I'm not a C++ dev.
http://php.net/manual/en/language.oop5.cloning.php

network byte order to host byte order conversion in php

I have requirement to develop a PHP server socket and a C client socket , visa versa.
I am thorough with TCP sockets in C and its concept.
I am stuck in on last thing.
I am able to send a whole structure from C client socket as follows
typedef struct _test {
char str[32];
char c;
int i;
float f;
}test;
//Some Coding ...
memset(&t,'\0',sizeof(test));
strcpy(t.str,"Sunny"); //String
t.c = 'M'; //Char
t.i = 26; //Integer
t.f = 98.8; //Float
//Send test STRUCT to server
if(send(sockfd,(void *)&t,sizeof(t),0) < 0)
{
perror("Send failed ");
exit(0);
}
//Some Coding ...
I am receiving this structure at PHP server socket as follows
...
$client = socket_accept($socket);
$input = socket_read($client, 1024);
$arr = unpack("Z32Str/a1Chr/iInt/fFlt", $input);
echo $arr['Str']; //Print String
echo $arr['Chr']; //Print Char
echo $arr['Int']; //Print Int
echo $arr['Flt']; //Print Float
...
I am getting string and char properly but am not getting Integer and Float properly , i am sure its network to host byte order (little endian,big endian) problem.
i.e. am getting integer value as 436207616
Can any one please tell me how to make equivalent fucntions to ntohl and ntohs in PHP.
P.S. :- Am quite new at PHP ... Please help
i have disabled the structure padding in C as below and it worked .....
How to disable structure padding ? As Follows ....
Following is the way to disable structure padding using pragma in C.
#pragma pack(push, 1)
//Define your structure here
#pragma pack(pop)
//Structure padding is re enabled.
#pragma pack(push,1)
typedef struct _test {
char str[32];
char c;
int i;
float f;
}test;
#pragma pack(pop)
Or:
I have kept padding on in C and do following at php side , and it worked ....
$arr = unpack("Z32Str/z4Chr/iInt/fFlt", $input);

send PHP string to C++

I am trying to pass over from php a string into C++, i managed to figure out how to pass numbers, but it doesn't work for letters. Here's what i have that works for PHP
<?php
$r = 5;
$s = 12;
$x= 3;
$y= 4;
$q= "Hello World";
$c_output=`project1.exe $r $s $x $y $q`; // pass in the value to the c++ prog
echo "<pre>$c_output</pre>"; //received the sum
//modify the value in php and output
echo "output from C++ programm is" . ($c_output + 1);
?>
This sends the variables r,s,x,y, and q to the C++ programm project1.exe and IT WORKS, but the problem is that it doesn't work for the string variable $q.
Here's the code that I have in my C++ programm, it's simple:
#include<iostream>
#include<cstdlib>
#include<string>
using namespace std;
int main(int in, char* argv[]) {
int val[2];
for(int i = 1; i < in; i++) { // retrieve the value from php
val[i-1] = atoi(argv[i]);
}
double r = val[0];
double s = val[1];
double x = val[2];
double y = val[3];
double q = val[4]; // here's the problem, as soon as i try to define val[4] as a string or char, it screws up
cout << r;
cout <<s;
cout << x;
cout << y;
cout << q;
// will output to php
return 0;
}
It works, but for the string "Hello world" which i pass through $q from PHP doesn't give me the string back (i know it's defined as a double, but as soon as i try to change it to a string or a char variable the code just doesn't compile).
Please explain to me how i have to go around this problem so that $q can be processed as a string. FYI, I am a newbie to programming (6 months in).
Try not converting the final argument using atoi(argv[i]). Just keep it as argv[i].
for(int i = 1; i < in-1; i++)
{
val[i-1] = atoi(argv[i]);
}
q = argv[i];
It doesn't work for letters because you are doing atoi(..)(which converts char-string to integer) in the C++ program.
Have some means of letting the program know what to expect -- whether a number or a string. May be the first argument can help the program differentiate, like may be the following:
$c_output = `project1.exe nnsnns 1 2 string1 3 4 string2`
Then you could do:
for(int i = 0/*NOTE*/,len=strlen(argv[1]); i < len; i++) { // retrieve the value from php
if (argv[1][i] == 'n'){
//argv[2+i] must be an integer
}else if (argv[1][i] == 's'){
//argv[2+i] is a string
}
}
Of course you should check if (strlen(argv[1]) == in-2).
BTW, in the C++ code above, val is a array holding 2 ints; and you are trying to access much beyond index 1.
To pass one single string to the C++ you would do something like the following:
$output = `project1.exe $q`; //Read below.
NOTE: $q must be a single word. No spaces, no extra characters like '|', '&', or any other character which the shell might interpret differently. $q must be clean before you pass that on to C++ Program. If $q is more than one word, use quotes.
C++ Part (Just try the following, then you can modify as you go along)
cout<<argv[1]<<endl;

C++ map lookup performance vs PHP array lookup performance

I can't understand the following and I'm hoping someone can shed some light on it for me:
In C++ if I create a vector of test data containing 2M different bits of text (testdata) then create a map using these strings as the index values, then look up all the values, like this:
//Create test data
for(int f=0; f<loopvalue; f++)
{
stringstream convertToString;
convertToString << f;
string strf = convertToString.str();
testdata[f] = "test" + strf;
}
time_t startTimeSeconds = time(NULL);
for(int f=0; f<2000000; f++) testmap[ testdata[f] ] = f; //Write to map
for(int f=0; f<2000000; f++) result = testmap[ testdata[f] ]; //Lookup
time_t endTimeSeconds = time(NULL);
cout << "Time taken " << endTimeSeconds - startTimeSeconds << "seconds." << endl;
It takes 10 seconds.
If I do seemingly at least the same in PHP:
<?php
$starttime = time();
$loopvalue = 2000000;
//fill array
for($f=0; $f<$loopvalue; $f++)
{
$filler = "test" . $f;
$testarray[$filler] = $f;
}
//look up array
for($f=0; $f<$loopvalue; $f++)
{
$filler = "test" . $f;
$result = $testarray[$filler];
}
$endtime = time();
echo "Time taken ".($endtime-$starttime)." seconds.";
?>
...it takes only 3 seconds.
Given that PHP is written in C does anyone know how PHP achieves this much faster text index lookup?
Thanks
C
Your loops are not absolutely equivalent algorithms.
Note that in the C++ version you have
testmap[ testdata[f] ] - this is actually a lookup + insert
testmap[ testdata[f] ] - 2 lookups
In the PHP versions you just have insert in the first loop and lookup in the second one.
PHP is interpreted - generally if you code is faster in PHP, check the code first ! ;-)
I suspect you benchmark the wrong things.
Anyway, I used your code (had to make some assumptions on your data types) and here are the results from my machine:
PHP:
Time taken 2 seconds.
C++ (using std::map):
Time taken 3 seconds.
C++ (using std::tr1::unordered_map):
Time taken 1 seconds.
C++ compiled with
g++ -03
Here is my test C++ code:
#include <map>
#include <sstream>
#include <string>
#include <vector>
#include <iostream>
#include <tr1/unordered_map>
int main(){
const int loopvalue=2000000;
std::vector<std::string> testdata(loopvalue);
std::tr1::unordered_map<std::string, int> testmap;
std::string result;
for(int f=0; f<loopvalue; f++)
{
std::stringstream convertToString;
convertToString << f;
std::string strf = convertToString.str();
testdata[f] = "test" + strf;
}
time_t startTimeSeconds = time(NULL);
for(int f=0; f<loopvalue; f++) testmap[ testdata[f] ] = f; //Write to map
for(int f=0; f<loopvalue; f++) result = testmap[ testdata[f] ]; //Lookup
time_t endTimeSeconds = time(NULL);
std::cout << "Time taken " << endTimeSeconds - startTimeSeconds << "seconds." << std::endl;
}
Conclusion:
You tested unoptimized C++ code, probably even compiled with VC++, which by default has a bounds check in std::vector::operator[] when compiled in debug mode.
There still is a difference of PHP to the optimised C++ code, when we use std::map, because of the difference in lookup complexity (see n0rd's answer), but C++ is faster when you use a Hashmap.
According to another question, associative arrays in PHP are implemented as hash tables, which have search complexity of O(1) on average, while std::map in C++ is a binary tree with search complexity of O(log n), which is slower.

PHP string to "unsigned long" (from C++)

I have this code in C++, which returns outputs the following number
int main(int argn, char** argv)
{
cout << (*((unsigned long*)"P3TF")) << endl;
cin.get();
return 0;
}
How can I achieve the above in PHP (i.e. the string "P3TF" in unsigned long int). I tried using the pack method:
<?php
$lol = pack('N', 'P3TF');
var_dump( $lol, // returns jumbled up characters
ord($lol[0]), // returns int 0
ord($lol[1]), // returns int 0
ord($lol[2]), // returns int 0
ord($lol[3]), // returns int 0
ord($lol[0]).ord($lol[1]).ord($lol[2]).ord($lol[3]) // returns 4 zeros as a string.
);
?>
I need it in bigendian byte order so I haven't used pack('V') or pack('L').
Anyone know how to achieve this?
Thanks!
If it's literally "P3TF" in the real code, why not convert it once, and define a constant in the PHP code?
Failing that, you need unpack, not pack. e.g. running
<?php
$in = 'P3TF';
$arr = unpack('N', $in);
printf("%08x\n", $arr[1]);
?>
Gives 50335446, which is the ASCII codes for 'P' '3' 'T' 'F' in hex (concatenated)

Categories