XML.com: XML From the Inside Out
oreilly.comSafari Bookshelf.Conferences.

advertisement

Building XML-RPC Clients in C

October 31, 2001

XML-RPC is a useful protocol for building cross-platform, client-server applications. Often XML-RPC is demonstrated with high-level interpreted languages like Perl and Python. In this article, Eric Kidd's XML-RPC C library is used to build a simple, yet powerful debugging client. Special care is taken to bring programmers with rusty C-hacking skills up to speed.

When It Absolutely Has to Be in C

XML-RPC is a wire protocol that describes an XML serialization format that clients and servers use to pass remote procedure calls to each other. There are two features that make this protocol worth knowing. The first is that the details of parsing the XML are hidden from the user. The second is that clients and servers don't need to be written in the same language. For more background information on XML-RPC, check out the Resources listed at the end of this article.

Many articles written about XML-RPC use Java, Perl, Python, or PHP to demonstrate building Web Services. However, real life programming requirements often mitigate against the programmer's first choice of implementation language, perhaps because access to a resource whose only API is a C library is required. In this case, building an XML-RPC server to this resource opens it up to any client that supports XML-RPC.

In high-level languages like Perl or Python, development can be rapid because the compile-run-edit test cycle is almost as fast as opening one's editor. In C, this isn't the case. Compiling a program can take a lot of time. But sometimes it's the only tool for the job. If your C skills are rusty, this article is for you. Because XML-RPC is a high-level protocol, it takes a good number of other C libraries to make the magic happen. Remember, even a simple client needs to be able to talk HTTP and parse XML, both of which are far beyond the built-in facilities of C. The first step is installing Eric Kidd's C library.

Installing the C XML-RPC Library

Eric Kidd's C/C++ interface to XML-RPC requires the W3 Consortium's WWW library. I used version 0.9.9 of the XML-RPC library and version 5.3.2 of the W3C's libwww for this article. Both packages compiled cleanly on my Red Hat 7.1 box using the standard ./configure && make, but there was a catch during the make install phase. The names of the shared libraries had an spurious '.0' appended to them. Those already familiar with the way shared libraries are found on a Linux box may skip the next section.


Joe Johnston has also written an article on Binary Data to Go: Using XML-RPC to Serve Up Charts on the Fly, which looks at how XML-RPC and Web services can create simple charts for client programs.


Both Kidd's and the W3C's libraries install shared libraries. These differ from the static libraries you might be more familiar with in that they are loaded during a program's runtime rather than being built into a monolithic static binary. In order for the system to find these shared libraries, you need to make sure that /etc/ld.so.conf lists the path to your shared libraries. In the case of the XML-RPC libraries listed above, /usr/lib must be listed. For existing binaries, you can check whether the system can locate the shared libraries by using the ldd command:

$ ldd <executable_name>

In the case of the program presented here, the ldd output will look something like:

[jjohn@marian src]$ ldd xmlrpc_debug
   
   libwwwxml.so.0 => /usr/lib/libwwwxml.so.0 (0x4002f000)
   libxmltok.so.0 => /usr/lib/libxmltok.so.0 (0x40032000)
   libxmlparse.so.0 => /usr/lib/libxmlparse.so.0 (0x40044000)
   libwwwzip.so.0 => /usr/lib/libwwwzip.so.0 (0x4004b000)
   libwwwinit.so.0 => /usr/lib/libwwwinit.so.0 (0x4004e000)
   libwwwapp.so.0 => /usr/lib/libwwwapp.so.0 (0x40051000)
   libmd5.so.0 => /usr/lib/libmd5.so.0 (0x40067000)
   libwwwhtml.so.0 => /usr/lib/libwwwhtml.so.0 (0x4006a000)
   libwwwtelnet.so.0 => /usr/lib/libwwwtelnet.so.0 (0x40076000)
        ...

If a library doesn't have a hex address next to it, the system can't find it. This can be solved by making sure that path in /etc/ld.so.conf is listed and then running ldconfig as root. Run the ldd command again to make sure all your shared libraries are visible.

As I mentioned above, the gotcha is that Kidd and W3C libraries don't name the shared libraries correctly (they install with an extra '.0' on the name). You will need to create symlinks with the kind of names that ldconfig expects. I used the Perl script in Listing 1 to do this, but any scripting tool will do.

Listing 1: Fixing library names

 

     1  #!/usr/bin/perl --
     2  # Look for these libs; ensure symlinks are right
     3  
     4  use strict;
     5  use constant LIB_DIR => '/usr/lib';
     6  
     7  my @libs = qw(
     8     libwwwxml libxmltok libxmlparse libwwwzip 
     9     libwwwinit libwwwapp libmd5 libwwwhtml libwwwtelnet 
    10     libwwwnews libwwwhttp libwwwmime libwwwgopher libwwwftp 
    11     libwwwfile libwwwdir libwwwcache libwwwstream libwwwmux 
    12     libwwwtrans libwwwcore libwwwutils libdl libz 
    13     libxmlrpc libxmlrpc_xmlparse libxmlrpc_xmltok
    14                );
    15  if( $> != 0 ){
    16    warn "ERROR: Must be root\n";
    17  }
    18  
    19  chdir LIB_DIR || die "ERROR: cd: $!";
    20  
    21  for my $lib (@libs){
    22    print "Looking for $lib\n";
    23    my @candidates = glob("$lib*0");
    24    for(@candidates){
    25      my ($link, $real);
    26      if( -l $_ ){
    27        $real = readlink($_);
    28        $link = "(is a symlink to $real)";
    29      }
    30      print "\t$_ $link\n";
    31  
    32      if( $real ){
    33        my $new = substr($_, 0, length($_) - 2);
    34        print "\tcreating a new symlink($new) to $real\n";
    35        unless( symlink $real, $new ){
    36          warn "WARN: symlink: $!\n";
    37        }
    38      }
    39    }
    40  }

Once you've squared this detail away, you're ready to start coding.

Pages: 1, 2, 3, 4

Next Pagearrow







close