This example shows some simple usage of ecore_pipe. We are going to create a pipe, fork our process, and then the child is going to communicate to the parent the result of its processing through the pipe.
As always we start with our includes, nothing special:
#include <unistd.h>
#include <Ecore.h>
The first thing we are going to define in our example is the function we are going to run on the child process, which, as mentioned, will do some processing and then will write the result to the pipe:
static void
{
int i, j;
char *buffer;
for (i = 0; i < 20; i++)
{
sleep(1);
buffer = malloc(sizeof(char) * i);
for (j = 0; j < i; j++)
buffer[j] = 'a' + j;
free(buffer);
}
struct _Ecore_Pipe Ecore_Pipe
A handle for pipes.
Definition: Ecore_Common.h:2416
Eina_Bool ecore_pipe_write(Ecore_Pipe *p, const void *buffer, unsigned int nbytes)
Writes on the file descriptor the data passed as parameter.
Definition: ecore_pipe.c:199
}
- Note
- The sleep was added so the parent process would think the child process was doing something interesting...
Next up is our function for handling data arriving in the pipe. It copies the data to another buffer, adds a terminating NULL and prints it. Also if it receives a certain string it stops the main loop(effectively ending the
program):
static void
handler(
void *data
EINA_UNUSED,
void *buf,
unsigned int len)
{
char *str = malloc(sizeof(char) * len + 1);
memcpy(str, buf, len);
str[len] = '\0';
printf("received %u bytes\n", len);
printf("content: %s\n", (const char *)str);
free(str);
if (len && !strncmp(buf, "close", len < 5 ? len : 5))
{
printf("close requested\n");
}
void ecore_main_loop_quit(void)
Quits the main loop once all the events currently on the queue have been processed.
Definition: ecore_main.c:1321
#define EINA_UNUSED
Used to indicate that a function parameter is purposely unused.
Definition: eina_types.h:339
}
And now on to our main function, we start by declaring some variables and initializing ecore:
int
main(void)
{
pid_t child_pid;
EAPI int ecore_init(void)
Sets up connections, signal handlers, sockets etc.
Definition: ecore.c:230
And since we are talking about pipes let's create one:
Ecore_Pipe * ecore_pipe_add(Ecore_Pipe_Cb handler, const void *data)
Creates two file descriptors (sockets on Windows).
Definition: ecore_pipe.c:93
Now we are going to fork:
- Note
- duh...
The child process is going to do the our fancy processing:
if (!child_pid)
{
do_lengthy_task(pipe);
}
void ecore_pipe_read_close(Ecore_Pipe *p)
Closes the read end of an Ecore_Pipe object created with ecore_pipe_add().
Definition: ecore_pipe.c:108
- Note
- It's very important to call ecore_pipe_read_close() here so that the child process won't read what it is writing to the pipe itself.
And the parent is going to run ecore's main loop waiting for some data:
else
{
}
void ecore_main_loop_begin(void)
Runs the application main loop.
Definition: ecore_main.c:1311
void ecore_pipe_write_close(Ecore_Pipe *p)
Closes the write end of an Ecore_Pipe object created with ecore_pipe_add().
Definition: ecore_pipe.c:176
- Note
- Calling ecore_pipe_write_close() here isn't important but since we aren't going to write in the pipe it is good practice.
And finally when done processing(the child) or done receiving(the parent) we delete the pipe and shutdown ecore:
return 0;
}
EAPI int ecore_shutdown(void)
Shuts down connections, signal handlers sockets etc.
Definition: ecore.c:371
void * ecore_pipe_del(Ecore_Pipe *p)
Frees an Ecore_Pipe object created with ecore_pipe_add().
Definition: ecore_pipe.c:100