bkxdr_0.01 - serialize C structs to/from compact byte streams and/or XML Noel Burton-Krahn <noel@burton-krahn.com> Jan 1, 2003 OVERVIEW This package is for serializing C data structures to portable compact byte streams or XML. You describe the data structures in a C-like type library, and the utility built here will generate the C code to do serialiation for you. Serialization handles most C types including strings, arrays, pointers (liked lists and graphs), and binary blobs. It's useful for sending structs as network messages, saving complex structs to disk, or making deep copies of complex linked structs. The code is based on Sun's XDR specification which is used to serialize structs for RPC. XDR is a standard (rfc1832) compact machine-portable binary format. I've modified Sun's code to use XML instead of the binary format, if you choose. So, you can serialize your structs to compact portable binary or readable XML. INSTALLATION tar zxf bkxdr-0.01.tar.gz cd bkxdr-0.01 (on unix, with expat installed) make (on win32, with msvc6+, nmake and cl in path, and cygwin) nmake -f makefile.win32 This will download and compile expat on win32, presuming you have wget installed. EXAMPLE First, you define your structs in an XDR type library file. /* mystruct_xdr.x */ struct MyStruct { string name<>; /* null-terminated string */ float vector<>; /* variable-length array */ opaque binary<>; /* binary blob */ struct MyStruct *next; /* linked lists are ok! */ }; typedef struct MyStruct MyStruct; Next, compile the serialization code with "rpcgen" to produce mystruct_xdr.c and mystruct_xdr.h rpcgen -c mystruct_xdr.x > mystruct_xdr.c rpcgen -h mystruct_xdr.x > mystruct_xdr.h Now you can use mystruct_xdr.h in your C program: /* mystruct.c */ #include "mystruct_xdr.h" int main(int argc, char **argv) { MyStruct orig1, orig2, copy; float vector1[] = {1.1f, 2.2f, 3.3f}; char binary1[] = {0xde, 0xad, 0xbe, 0xef}; char buf[4096]; int len; /* set up a cople of linked structures, orig1 and orig2 */ memset(&orig1, 0, sizeof(orig1)); orig1.name = "orig1"; orig1.vector.vector_val = vector1; orig1.vector.vector_len = sizeof(vector1)/sizeof(*vector1); orig1.binary.binary_val = binary1; orig1.binary.binary_len = sizeof(binary1)/sizeof(*binary1); memset(&orig2, 0, sizeof(orig2)); orig2.name = "orig2"; orig1.next = &orig2; /* serialize orig1 and linked orig2 to buf */ len = xdr_pack(xdr_MyStruct, &orig1, XDR_ENCODE, XDR_BINARY, buf, sizeof(buf)); printf("encoded orig1 to binary len=%d\n", len); /* now you can save buf to disk, or fire it over the net */ /* deserialize buf to copy */ memset(©, 0, sizeof(copy)); xdr_pack(xdr_MyStruct, ©, XDR_DECODE, XDR_BINARY, buf, len); /* copy contains malloced data, so you must free it */ xdr_free(xdr_MyStruct, ©); /* the same serialization, but this time to/from xml */ len = xdr_pack(xdr_MyStruct, &orig1, XDR_ENCODE, XDR_XML, buf, sizeof(buf)); printf("encoded orig1 to xml len=%d\n%s\n", len, buf); memset(©, 0, sizeof(copy)); xdr_pack(xdr_MyStruct, ©, XDR_DECODE, XDR_XML, buf, len); len = xdr_pack(xdr_MyStruct, ©, XDR_ENCODE, XDR_XML, buf, sizeof(buf)); printf("encoded copy to xml len=%d\n%s\n", len, buf); xdr_free(xdr_MyStruct, ©); return 0; } Finally, compile it cc -o mystruct mystruct.c mystruct_xdr.c bkxdr.lib SEE ALSO Test programs in this directory: mystruct.c, xdr_t.c, xdrstream_t.c LICENSE The sunrpc code is from GNU Libc, and is covered by a Sun Microsystems license. (http://www.gnu.org/software/libc/libc.html) This uses James Clark's excellent expat library (http://www.jclark.com/xml/expat.html) Changes are covered under the GNU GPL. NOTES I have not tested endian comatibiliy on non-intel architectures, although the original sunrpc code works there.