Adding an Ecore_exe example to documentation.

Author:    Guilherme Iscaro <iscaro@profusion.mobi>

SVN revision: 71174
This commit is contained in:
Jonas M. Gastal 2012-05-16 17:23:51 +00:00
parent 5f389075b7
commit 2dc0014f4a
6 changed files with 306 additions and 4 deletions

View File

@ -21,6 +21,7 @@
* @li @ref Ecore_Evas_Window_Sizes_Example_c
* @li @ref Ecore_Evas_Buffer_Example_01_c
* @li @ref Ecore_Evas_Buffer_Example_02_c
* @li @ref Ecore_exe_simple_example_c
*/
/**
@ -914,6 +915,20 @@
* See @ref ecore_timer_example_c "the example explained".
*/
/**
* @example ecore_exe_example_child.c
* This is a child process used to receive messages and send it back
* to its father.
* Check the @ref Ecore_exe_simple_example_c "Full tutorial"
*/
/**
* @example ecore_exe_example.c
* This is a process that will send messages to a child and it will stop
* when it receives "quit".
* Check the @ref Ecore_exe_simple_example_c "Full tutorial"
*/
/**
* @example ecore_fd_handler_example.c
* This example shows how to setup and use an fd_handler. See
@ -1527,3 +1542,128 @@
* @include ecore_evas_buffer_example_02.c
* @example ecore_evas_buffer_example_02.c
*/
/**
* @page Ecore_exe_simple_example_c Ecore_exe
* Creating a processes and IPC (Inter process communication)
*
* In this example we will show how to create a new process and communicate
* with it in a portable way using the Ecore_exe module.
*
* In this example we will have two process and both will communicate with each
* other using messages. A father process will start a child process and it will
* keep sending messages to the child until it receives a message to quit.
* To see the full source use the links:
* @li @ref ecore_exe_example.c "Father"
* @li @ref ecore_exe_example_child.c "Child"
*
* Let's start the tutorial. The implementation of the child it's pretty simple.
* We just read strings from stdin and write a message in the stdout. But you
* should be asking yourself right know. "If I'm receiving data from an other
* process why I'm reading and writing in stdin/stdout?". That's because, when
* you spawn a process using the Ecore_Exe module it will create a pipe between
* the father and the child process and the stdin/stdout of the child process
* will be redirected to the pipe. So when the child wants to receive or send
* data to the father, just use the stdin/stdout.
* However the steps to send data from the father to the child is quite
* different, but we will get there.
*
* The child will register a fd handler to monitor the stdin.
* So we start registering the ecore FD handler:
* @dontinclude ecore_exe_example_child.c
* @skip ecore_main_fd_handler_add
* @until ;
*
* If you don't remenber the parameters of @ref ecore_main_fd_handler_add,
* please check its documentation.
*
* Now that we have our handler registered we will start the ecore's main loop:
* @skipline ecore_main_loop_begin
*
* Now let's take a look in the callback function. Its a simple function
* that will read from stdin 3 times and at the third time will say
* to the father: "quit".
* @dontinclude ecore_exe_example_child.c
* @skip static Eina_Bool
* @until }
* @until }
* @until }
* @until }
*
* You may notice that we are sending the messages to stdout, and our father
* will receive it. Also our string must have a "\n" because the string will
* be buffered in the pipe until it finds EOF or a "newline" in our case we
* won't have a EOF unless we close the pipe, so we use the "\n" char.
*
* One more thing, we use fflush(stdout) because probably our message won't
* fill our entire buffer and the father would never receive the message. So we
* use this function to flush the buffer and the father can receive as fast as
* possible.
*
* Now that we have our child ready, let's start our work in the father's source
* code.
*
* We start creating the child process like this:
* @dontinclude ecore_exe_example.c
* @skip childHandle = ecore_exe_pipe_run
* @until ;
*
* With the command above we are creating our child process, the first
* parameter is the command to be executed, the second are the pipe flags and
* in our case we will write and read in the pipe so we must say what we are
* doing in the pipe. You may notice the flag ECORE_EXE_PIPE_READ_LINE_BUFFERED,
* this means that reads are buffered until I find a newline. And the third
* parameter is data that we would like to send to the process in its creating.
* This case we are sending nothing, so just use NULL.
*
* Then we check if the process was created:
* @skip if
* @until }
*
* After this we get the PID of the child process and just print it in the screen.
* The PID stands for Process identification. This is just an internal
* identifier of your process:
*
* @skip childPid
* @until fprintf
* @until fprintf
*
* The way that Ecore_exe works is: when we want to read data sent from
* our child we must use an ecore event.
* So let's start register our event listener:
* @skipline ecore_event_handler_add
*
* Now to send messages to our child we will use a timer, so every 1 second we
* will send a message to the child.
* @skipline ecore_timer_add
*
* After all this we start the main loop. Now let's pass to the callback
* functions.
*
* Now we will see how we actually send the data and receive it.
* Let's start with _sendMessage:
* @dontinclude ecore_exe_example.c
* @skip _sendMessage(void *data)
* @until }
*
* We use ecore_exe_send to send data to the child process, it's pretty simple.
* To know what the parameters stands for, check the docs.
*
* @note The function @b ecore_exe_send will never block your program, also
* there is no partial send of the data. This means either the function will
* send all the data or it will fail.
*
* Now let's take a look in our event callback and see how we retrieve the
* messages.
* @dontinclude ecore_exe_example.c
* @skip static Eina_Bool
* @until }
* @until }
*
* It's just like an normal event, we get a reference to Ecore_Exe_Event_Data,
* extract the data and then show it in the screen.
*
* And that's it, after all it's not complicated to create a process and
* communicate with it.
*
*/

View File

@ -55,7 +55,9 @@ SRCS = \
ecore_evas_basics_example.c \
ecore_evas_buffer_example_01.c \
ecore_evas_buffer_example_02.c \
ecore_evas_ews_example.c
ecore_evas_ews_example.c \
ecore_exe_example.c \
ecore_exe_example_child.c
EXTRA_DIST = $(SRCS) \
$(srcdir)/red.png
@ -95,7 +97,9 @@ examples_PROGRAMS += \
ecore_evas_buffer_example_02 \
ecore_evas_ews_example \
ecore_client_bench \
ecore_server_bench
ecore_server_bench \
ecore_exe_example \
ecore_exe_example_child
ecore_con_lookup_example_LDADD = $(ECOREBASELDADD) $(top_builddir)/src/lib/ecore_con/libecore_con.la
ecore_con_url_headers_example_LDADD = $(ECOREBASELDADD) $(top_builddir)/src/lib/ecore_con/libecore_con.la

View File

@ -0,0 +1,93 @@
/**
Compile with gcc -o ecore_exe_example ecore_exe_example.c `pkg-config --cflags --libs ecore`
*/
#include <stdio.h>
#include <string.h>
#include <Ecore.h>
#define BUFFER_SIZE 1024
static Eina_Bool
_msg_from_child_handler(void *data, int type, void *event)
{
Ecore_Exe_Event_Data *dataFromProcess = (Ecore_Exe_Event_Data *)event;
char *msg = (char *) dataFromProcess->data;
if (strcmp(msg, "quit") == 0)
{
fprintf(stdout, "My child said to me, QUIT!\n");
ecore_main_loop_quit();
}
else
fprintf(stdout, "I received a message from my child: %s\n", msg);
return ECORE_CALLBACK_DONE;
}
static Eina_Bool
_sendMessage(void *data)
{
static int numberOfMessages = 0;
Ecore_Exe *childHandle = (Ecore_Exe*) data;
char msg[BUFFER_SIZE];
sprintf(msg, " Message: %d\n", numberOfMessages);
numberOfMessages++;
if (ecore_exe_send(childHandle, msg, strlen(msg)) != EINA_TRUE)
fprintf(stderr, "Could not send my name to the child\n");
else
fprintf(stdout,
"I'm the father and I sent this message to the child: %s\n", msg);
return ECORE_CALLBACK_RENEW;
}
int
main(int argc, char **argv)
{
pid_t childPid;
Ecore_Exe *childHandle;
if (!ecore_init())
goto exit;
childHandle = ecore_exe_pipe_run("./ecore_exe_example_child",
ECORE_EXE_PIPE_WRITE |
ECORE_EXE_PIPE_READ_LINE_BUFFERED |
ECORE_EXE_PIPE_READ, NULL);
if (childHandle == NULL)
{
fprintf(stderr, "Could not create a child process!\n");
goto ecore_shutdown;
}
childPid = ecore_exe_pid_get(childHandle);
if (childPid == -1)
fprintf(stderr, "Could not retrive the PID!\n");
else
fprintf(stdout, "The child process has PID:%d\n", childPid);
ecore_event_handler_add(ECORE_EXE_EVENT_DATA, _msg_from_child_handler, NULL);
ecore_timer_add(1, _sendMessage, childHandle);
ecore_main_loop_begin();
ecore_exe_free(childHandle); //This will not affect the child process
ecore_shutdown();
return EXIT_SUCCESS;
ecore_shutdown:
ecore_shutdown();
exit:
return EXIT_FAILURE;
}

View File

@ -0,0 +1,57 @@
/**
Compile with gcc -o ecore_exe_example_child ecore_exe_example_child.c `pkg-config --cflags --libs ecore`
*/
#include <stdio.h>
#include <unistd.h>
#include <Ecore.h>
#define BUFFER_SIZE 1024
static Eina_Bool
_fd_handler_cb(void *data, Ecore_Fd_Handler
*fd_handler)
{
static int numberOfMessages = 0;
char message[BUFFER_SIZE];
fgets(message, BUFFER_SIZE, stdin);
numberOfMessages++;
if (numberOfMessages < 3)
{
fprintf(stdout, "My father sent this message to me:%s\n", message);
fflush(stdout);
return ECORE_CALLBACK_RENEW;
}
else
{
fprintf(stdout, "quit\n");
fflush(stdout);
ecore_main_loop_quit();
return ECORE_CALLBACK_DONE;
}
}
int
main(int argc, char **argv)
{
if (!ecore_init())
goto error;
ecore_main_fd_handler_add(STDIN_FILENO,
ECORE_FD_READ,
_fd_handler_cb,
NULL, NULL, NULL);
ecore_main_loop_begin();
ecore_shutdown();
return EXIT_SUCCESS;
error:
return EXIT_FAILURE;
}

View File

@ -838,9 +838,13 @@ EAPI void *ecore_event_current_event_get(void);
* @defgroup Ecore_Exe_Group Process Spawning Functions
*
* This module is responsible for managing portable processes using Ecore.
* With this module you're able to spawn processes and you also can pause, quit your spawned processes
* An interaction between your process and those spawned is possible using pipes or signals.
* With this module you're able to spawn processes and you also can pause,
* quit your spawned processes.
* An interaction between your process and those spawned is possible
* using pipes or signals.
*
* Example
* @li @ref Ecore_exe_simple_example_c
*
* @ingroup Ecore_Main_Loop_Group
*

View File

@ -368,6 +368,10 @@ ecore_exe_run_priority_get(void)
* Spawns a child process.
*
* This is now just a thin wrapper around ecore_exe_pipe_run()
* @note When you use this function you will have no permissions
* to write or read on the pipe that connects you with the spwaned process.
* If you need to do that use ecore_exe_pipe_run() with the
* appropriated flags.
*
* @param exe_cmd The command to run with @c /bin/sh.
* @param data Data to attach to the returned process handle.