forked from enlightenment/efl
Adding an Ecore_exe example to documentation.
Author: Guilherme Iscaro <iscaro@profusion.mobi> SVN revision: 71174
This commit is contained in:
parent
5f389075b7
commit
2dc0014f4a
|
@ -21,6 +21,7 @@
|
||||||
* @li @ref Ecore_Evas_Window_Sizes_Example_c
|
* @li @ref Ecore_Evas_Window_Sizes_Example_c
|
||||||
* @li @ref Ecore_Evas_Buffer_Example_01_c
|
* @li @ref Ecore_Evas_Buffer_Example_01_c
|
||||||
* @li @ref Ecore_Evas_Buffer_Example_02_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".
|
* 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
|
* @example ecore_fd_handler_example.c
|
||||||
* This example shows how to setup and use an fd_handler. See
|
* This example shows how to setup and use an fd_handler. See
|
||||||
|
@ -1527,3 +1542,128 @@
|
||||||
* @include ecore_evas_buffer_example_02.c
|
* @include ecore_evas_buffer_example_02.c
|
||||||
* @example 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
|
@ -55,7 +55,9 @@ SRCS = \
|
||||||
ecore_evas_basics_example.c \
|
ecore_evas_basics_example.c \
|
||||||
ecore_evas_buffer_example_01.c \
|
ecore_evas_buffer_example_01.c \
|
||||||
ecore_evas_buffer_example_02.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) \
|
EXTRA_DIST = $(SRCS) \
|
||||||
$(srcdir)/red.png
|
$(srcdir)/red.png
|
||||||
|
@ -95,7 +97,9 @@ examples_PROGRAMS += \
|
||||||
ecore_evas_buffer_example_02 \
|
ecore_evas_buffer_example_02 \
|
||||||
ecore_evas_ews_example \
|
ecore_evas_ews_example \
|
||||||
ecore_client_bench \
|
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_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
|
ecore_con_url_headers_example_LDADD = $(ECOREBASELDADD) $(top_builddir)/src/lib/ecore_con/libecore_con.la
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -838,9 +838,13 @@ EAPI void *ecore_event_current_event_get(void);
|
||||||
* @defgroup Ecore_Exe_Group Process Spawning Functions
|
* @defgroup Ecore_Exe_Group Process Spawning Functions
|
||||||
*
|
*
|
||||||
* This module is responsible for managing portable processes using Ecore.
|
* 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
|
* With this module you're able to spawn processes and you also can pause,
|
||||||
* An interaction between your process and those spawned is possible using pipes or signals.
|
* 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
|
* @ingroup Ecore_Main_Loop_Group
|
||||||
*
|
*
|
||||||
|
|
|
@ -368,6 +368,10 @@ ecore_exe_run_priority_get(void)
|
||||||
* Spawns a child process.
|
* Spawns a child process.
|
||||||
*
|
*
|
||||||
* This is now just a thin wrapper around ecore_exe_pipe_run()
|
* 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 exe_cmd The command to run with @c /bin/sh.
|
||||||
* @param data Data to attach to the returned process handle.
|
* @param data Data to attach to the returned process handle.
|
||||||
|
|
Loading…
Reference in New Issue