Writing Portable C Code with APR
Garrett Rooney
CollabNet
Introduction
- What is APR?
- Who am I?
- Subversion Developer
- APR Committer
- Apache HTTP Server Committer
- Apache Software Foundation Member
Getting APR
- Two options:
- The Website - http://apr.apache.org/download.cgi
- The SVN Repository - http://svn.apache.org/repos/asf/apr/
- Get a 1.2.x release
- Newer, Better, Faster...
- Better Supported
- Probably Want APR-Util
- On Win32 You Want APR-Iconv
Building on Unix
$ export P=$HOME/apr
$ tar zxvf apr-1.2.7.tar.gz
$ cd apr-1.2.7
$ ./configure --prefix=$P
$ make && make install
$ tar zxvf apr-util-1.2.7.tar.gz
$ cd apr-util-1.2.7
$ ./configure --prefix=$P --with-apr=$P/bin/apr-1-config
$ make && make install
Building on Windows
- Uses Visual C++
- Instructions for VC 6.0 on the Website
- For the Impatient or Cheap:
- Install Visual Studio Express C++
- Install Microsoft Platform SDK
- Open APR's test\testall.dsp file
- Run Build
Hello APR World
#include <apr.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
apr_pool_t *pool;
apr_file_t *out;
apr_initialize();
atexit(apr_terminate());
apr_pool_create(&pool, NULL);
apr_file_open_stdout(&out, pool);
apr_file_printf(out, "Hello World\n");
apr_pool_destroy(pool);
return EXIT_SUCCESS;
}
How To Compile It
# first, cflags (i.e. -g -O2 -pthread)
$ export CFLAGS=`apr-1-config --cflags`
# then, cppflags (i.e. -I/path/to/includes -D_REENTRANT)
$ export CPPFLAGS=`apr-1-config --cppflags`
# then link options (i.e. -L /path/to/libs -lapr-1)
$ export LINK_LD=`apr-1-config --link-ld`
$ cc $CFLAGS $CPPFLAGS $LINK_LD program.c -o program
Things to note
- Initialize APR and set up apr_terminate via atexit
- Create a global pool
- Do our thing
- Destroy the pool
What's With The Pool?
- Resources in APR are managed with pools
- Memory Allocation
- Filehandles
- Sockets
- Arbitrary user defined things
- You clean up the pool, it cleans up other stuff
- A Hierarchy, clear/destroy the parent, it destroys children
Proper Pool Usage
const char *find_interesting_string(apr_pool_t *pool) {
const char *interesting = NULL, *temp;
apr_pool_t *subpool;
int i;
apr_pool_create (&subpool, pool);
for (i = 0; i < 100; ++i) {
apr_pool_clear(subpool);
function_that_uses_temp_memory(&temp, subpool);
if (retval_is_interesting(temp)) {
interesting = apr_pstrdup(pool, temp);
break;
}
}
apr_pool_destroy(subpool);
return interesting;
}
Error Handling
- APR functions return
apr_status_t
- Basically means
errno
in most cases
- Use macros to portably check for particular errors
Good Error Handling
apr_status_t some_function(apr_pool_t *pool) {
apr_status_t err;
apr_file_t *fp;
err = apr_file_open(&fp, "the-file-name", APR_READ,
APR_OS_DEFAULT, pool);
if (APR_STATUS_IS_SUCCESS(err)) {
/* read from the file... */
} else if (APR_STATUS_IS_ENOENT(err)) {
/* ok, the file wasn't found. do something useful
* here. */
return err;
} else {
return err;
}
return APR_SUCCESS;
}
Data Structues
- APR provides several common data structures
- Battle tested
- Work with pools
apr_hash_t
- Hash Table
apr_array_header_t
- Variable Length Array
APR-Util
- Library built on top of APR
- Provides portable abstractions for third party libraries
- DBD - SQL Database abstraction
- DBM - Berkeley DB, GDBM, SDBM, etc.
- LDAP - Portably use different LDAP client toolkits
- Xlate - Portable iconv
- Useful abstractions implemented on top of APR
- Bucket Brigades - HTTPD's stream abstraction
- Memcached client library
File I/O
cat/cat.c
- Output is opened in top level pool
- Subpool is used to hold input file
- Macro used to check for EOF
- Pool cleanups handle closing of files
Network I/O
XXX network client
Echo Server
echoserver/echoserver.c
- Creates a top level pool to pass to
serve()
function
- Creates socket in that pool
- Binds and listens on the port in question
- Creates a subpool for use processing the connection
-
apr_socket_accept
and then apr_socket_recv
and apr_socket_send
Poll
XXX polling network server
Process Management
XXX fork
XXX executing processes
Threads
XXX threaded network server
Shared Memory
XXX come up with an example
Thank You
That's all Folks.