Communicate C Program and PHP

communicate c program and php

Some simple solutions I can think of are:

Redis

You could use redis as your ipc using hiredis as your c client library. I never used hiredis library before but did it just now for you to test and the library is really good. I could have known it because redis is the best piece of C code I know :).

modify example.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hiredis.h"

int main(void) {
redisContext *c;
redisReply *reply;

c = redisConnect((char*)"127.0.0.1", 6379);
if (c->err) {
printf("Connection error: %s\n", c->errstr);
redisFree(c);
exit(1);
}

/* Blocking pop. */
reply = redisCommand(c, "BLPOP php 0");
if (reply->type == REDIS_REPLY_ARRAY) {
if (reply->elements == 2) {
printf("%s\n", reply->element[1]->str);
}
}
freeReplyObject(reply);
redisFree(c);
return 0;
}

Compile and run example:

make
./hiredis-example

from ./redis-cli:

from another tab start start redis-cli(for prototyping) and issue the following command. You should replace this with predis as php client library, but that is going to be very easy:

lpush php "Hello from PHP"

Inside running hiredis-example:

You should see the message "Hello from PHP". Easy as pie if you ask me :).

Named pipes

You could use a named pipes.

Sockets

You could read the Beej's Guide to Network Programming Using Internet Sockets. In my opinion this is a very good read.

Communicating between a C- and a PHP-Program

I suppose that you write both the PHP and the C code yourself, and that you have access to compilers and so on? What I would do is not at all start up a different process and use inter-process-communication, but write a PHP C++ extension that does this all for you.

The extension starts up a new thread, and this thread picks up all instruction from an in-memory instruction queue. When you're ready to pick up the result, the final instruction is sent to the thread (the instruction to close down), and when the thread is finally finished, you can pick up the result.

You could use a program like this:

#include <phpcpp.h>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <unistd.h>

/**
* Class that takes instructions from PHP, and that executes them in CPP code
*/
class InstructionQueue : public Php::Base
{
private:
/**
* Queue with instructions (for simplicity, we store the instructions
* in strings, much cooler implementations are possible)
*
* @var std::queue
*/
std::queue<std::string> _queue;

/**
* The final result
* @var std::string
*/
std::string _result;

/**
* Counter with number of instructions
* @var int
*/
int _counter = 0;

/**
* Mutex to protect shared data
* @var std::mutex
*/
std::mutex _mutex;

/**
* Condition variable that the thread uses to wait for more instructions
* @var std::condition_variable
*/
std::condition_variable _condition;

/**
* Thread that processes the instructions
* @var std::thread
*/
std::thread _thread;

/**
* Procedure to execute one specific instruction
* @param instruction
*/
void execute(const std::string &instruction)
{
// @todo
//
// add your own the implementation, for now we just
// add the instruction to the result, and sleep a while
// to pretend that this is a difficult algorithm

// append the instruction to the result
_result.append(instruction);
_result.append("\n");

// sleep for a while
sleep(1);
}

/**
* Main procedure that runs the thread
*/
void run()
{
// need the mutex to access shared resources
std::unique_lock<std::mutex> lock(_mutex);

// keep looping
while (true)
{
// go wait for instructions
while (_counter == 0) _condition.wait(lock);

// check the number of instructions, leap out when empty
if (_queue.size() == 0) return;

// get instruction from the queue, and reduce queue size
std::string instruction(std::move(_queue.front()));

// remove front item from queue
_queue.pop();

// no longer need the lock
lock.unlock();

// run the instruction
execute(instruction);

// get back the lock for the next iteration of the main loop
lock.lock();
}
}

public:
/**
* C++ constructor
*/
InstructionQueue() : _thread(&InstructionQueue::run, this) {}

/**
* Copy constructor
*
* We just create a brand new queue when it is copied (copy constructor
* is required by the PHP-CPP library)
*
* @param queue
*/
InstructionQueue(const InstructionQueue &queue) : InstructionQueue() {}

/**
* Destructor
*/
virtual ~InstructionQueue()
{
// stop the thread
stop();
}

/**
* Method to add an instruction
* @param params Object representing PHP parameters
*/
void add(Php::Parameters ¶ms)
{
// first parameter holds the instruction
std::string instruction = params[0];

// need a mutex to access shared resources
_mutex.lock();

// add instruction
_queue.push(instruction);

// update instruction counter
_counter++;

// done with shared resources
_mutex.unlock();

// notify the thread
_condition.notify_one();
}

/**
* Method to stop the thread
*/
void stop()
{
// is the thread already finished?
if (!_thread.joinable()) return;

// thread is still running, send instruction to stop (which is the
// same as not sending an instruction at all but just increasing the
// instruction counter, lock mutex to access protected data
_mutex.lock();

// add instruction
_counter++;

// done with shared resources
_mutex.unlock();

// notify the thread
_condition.notify_one();

// wait for the thread to finish
_thread.join();
}

/**
* Retrieve the result
* @return string
*/
Php::Value result()
{
// stop the thread first
stop();

// return the result
return _result;
}
};

/**
* Switch to C context to ensure that the get_module() function
* is callable by C programs (which the Zend engine is)
*/
extern "C" {
/**
* Startup function that is called by the Zend engine
* to retrieve all information about the extension
* @return void*
*/
PHPCPP_EXPORT void *get_module() {

// extension object
static Php::Extension myExtension("InstructionQueue", "1.0");

// description of the class so that PHP knows
// which methods are accessible
Php::Class<InstructionQueue> myClass("InstructionQueue");

// add methods
myClass.method("add", &InstructionQueue::add);
myClass.method("result", &InstructionQueue::result);

// add the class to the extension
myExtension.add(std::move(myClass));

// return the extension
return myExtension;
}
}

You can use this instruction queue from a PHP script like this:

<?php

$queue = new InstructionQueue();

$queue->add("instruction 1");
$queue->add("instruction 2");
$queue->add("instruction 3");

echo($queue->result());

As an example I've only added a silly implementation that sleeps for a while, but you could run your API-calling functions in there.

The extension uses the PHP-CPP library (see http://www.php-cpp.com).

How to set up communication between PHP and C++?

I think the easiest way is:

1) PHP -> C++ : tcp

2) C++ -> PHP : http

Will try to explain.

1) To take something from C++ app PHP connects to that app using stream_socket_client function. C++ app is listening on host and port using socket, bind and listen functions. As soon as connection arrives C++ app accept it and then in a separate std::thread serves it (recv to get request, send to send response). How to socket.

2) As PHP is working under Apache Web Server, I think the easiest way is use of libcurl library to make HTTP request from C++ app. How to curl.

How to make PHP and C/C++ interact with each other

It's possible and you have multiple ways to achieve that.

  • write an extension (as it was already suggested)
  • call your C program with 'exec()'
  • use Gearman
  • run C program as a service and communicate with it via pipe or a socket

From the above I would choose an extension or Gearman.

C program that connects to index.php on xampp server

It depends what you actually want to achieve, i.e. what you mean by 'connect' a c program to an index.php ?

The first thing you should realize is that what we are talking about here are two processes: (a) the c program and (b) whatever interpreter that executes the PHP script (Probably a web server).

You want to exchange data between two processes, thus we talk about Interprocess Communication.

In the Wikipedia article you see a table listing several means:

  • Files: Your PHP script could write to a file, the c program read from it (or, under Unix, Pipes would be even better suited)

  • Sockets: Just as you mentioned already, one of the programs could establish a connection via sockets and exchange their data over this connection.

  • other means (have a look at the table)

Since your PHP script is probably run within a web server, the socket solution would be promising:
The web server already listens for incoming connections, and provides a decent protocol to exchange data: HTTP .

I will not repeat the answer by Basile , but just give an example for how to exchange some data between the c program and the PHP script with a web server using CGI:

The web server provides a URL, that will invoke the PHP script, like http://test.me/test.php .

Now, the procedure would be:

  1. The C program establishes a TCP connection to socket test.me:80
  2. The c program sends over a HTTP GET request by transmitting text in the form of

    GET /test.php?a=31&b=19 http/1.1

  3. The server will invoke the index.php, providing it with the key value pairs a=31, b=19

  4. The script will do stuff, and print something to stdout like:

    abc

(This is not a valid HTTP response, but its sufficient to scetch the procedure in general)


  1. The web server will send back the output of the php script abc over the connection to the c program.

As you see, in this example, you transferred

  1. a=31, b=19 from the c program to the web server/index.php
  2. abc from the web server/index.php to the c program

In general, the best solution depends on what you want to accomplish. I assume your example is just an example, and you could solve it the way I drafted above. However, if you really just wanted to have something printed to your console, just have your index.php write it to a file/pipe and the c program read the file...

This way or the other, I feel there is much for you to explore ...

Furthermore, I want to clarify one last thing:
I used 'c program' for the sake of simplicity, but i need not be a c program, but your problem referrs to an arbitrary process, it could also be a python script run by the python interpreter or ...

What is a good Inter-Process Communication method between C and PHP in Linux

Possibly the simplest solution you can find is to use pipes. The processes would have an open pipe for reading "calls" and answering them in the same fashion.

One possible way of setting this up is to have a pair of named pipes (mkfifo) in a specific or variable location. Such pipes are known to both this process and PHP. The process would block reading a loop for requests/commands in some textual "protocol" and write back to PHP through the other pipe. In this way both PHP and the external processes could be stopped/killed and restarted and the communications path would still be stable.

You might need to do something else in order to verify whether the process is actually running, if this is needed, but a simple "ping" command over this "protocol" would be enough.

This assumes:

  • you have the possibility of making improvements to the processes that communicates to the hardware (otherwise, your are bound to whatever it already offers)
  • you don't have high performance requirements (pipes are relatively slow)
  • there's no parallelism problem in case of concurrent accesses from the PHP script to process (unless you do some locking, 2 concurrent requests would be written mixed in the pipe)

There are off course other ways of achieving this, but I find hard to consider other way that is as simple as this. Queueing (d-bus, others), as suggested in some comments, are just building on top of this idea but adding more complexity IMHO, therefore, if no functionality provided by these other services is needed, pipes should be enough.



Related Topics



Leave a reply



Submit