7 Mar 2013

gcc - compile shared library

the Program to compile as shared library

string.h

/** string.h
 *
 * $Id$
 */

#ifndef STINRG_H_
#define STINRG_H_

#ifndef DEFAULT_BLOCKSIZE
 // num. bytes of junks of memory to allocate from the heap
 #define DEFAULT_BLOCKSIZE 128
#endif

#include <stdio.h>
#include <stdlib.h>

/** datatype to hold the character data */
struct string_t {
 int memsize;
 int length;
 char *text;
 int error;
};
typedef struct string_t string;

// function declarations
string str_redfile(FILE *file, int bs);
void str_dump(string *s);
unsigned long str_memsize(string *s);

#endif /* STINRG_H_ */

string.c

/** C example for reading file and allocating memory dynamically.
 *
 * Will read a file from disk while dynamically allocating memory.
 *
 * Example usage: ./exe [file-name]
 *
 * $Id$
 */

#include "string.h"

/** Read file from FILE pointer
 *
 * Reads data from FILE *file and dynamically allocates memory from the heap
 * to store the read data. If memory allocation fails, the returned string
 * struct's member error will equal to 1.
 *
 * If reading the file works, string.error will be 0.
 */
string str_redfile(FILE *file, int bs) {
 int charsize = sizeof(char);
 int charcount = 0;
 int blocksize;
 if (!bs)
  blocksize = DEFAULT_BLOCKSIZE;
 else
  blocksize = bs;
 int memsize = blocksize;
 char *line = (char*) malloc(charsize * (memsize+1));
 char *linep = line;

 string l;
 l.error = 0;
 l.length = 0;
 l.memsize = memsize;
 l.length = charcount;
 l.text = linep;

 while (1) {

  if(charcount > memsize) {
   // reallocate memmory
   memsize = memsize+blocksize;
   char *al = (char*) realloc(linep, charsize * (memsize+1));

   if (al == NULL) {
    fprintf(stderr, "Error, out of memory.\n");
    *line = '\0';
    l.text = linep;
    l.error = 1;
    return l;
   }
  }

  char c = fgetc(file);

  //if (c == '\n' || c == '\r' || c == EOF) {
  if (c == EOF) {
   charcount--;
   break;
  }

  // remember input char
  *line = c;
  *(line++);
  charcount++;
 }

 *line = '\0';
 l.text = linep;
 l.memsize = memsize;
 l.length = charcount;

 return l;
}

/** return allocated memory of a string struct
 */
unsigned long str_memsize(string *s) {
 return sizeof(string) + (s->memsize) + 1;
}

/** print struct string info
 */
void str_dump(string *s) {
 if (s->error == 0) {
  printf("memsize: %d\n", s->memsize);
  printf("length:  %d\n", s->length);
  printf("error:   %d\n", s->error);
  printf("text:    %.*s\n", 10, s->text);
  printf("total:   %lu\n", str_memsize(s));
 } else
  printf("Error: %d.\n", s->error);
}

test.c

/** test shared library
 *
 * an example how to use a shared library in a C program.
 *
 * $Id$
 */

#include "string.h"

/** main entry point
 */
int main(int argc, char **argv) {

 // we need 1 argument, the file name
 if(argc < 2) {
  fprintf(stderr, "Usage: %s [file]\n", argv[0]);
  exit(1);
 }

 // try to open the file
 FILE *f = fopen(argv[1], "r");
 if (f == NULL) {
  fprintf(stderr, "Error: failed to open file: %s\n", argv[1]);
  exit(2);
 }

 // allocate memory for storing the string and read contents
 string l = str_redfile(f, 0);

 // close file
 fclose(f);

 // check if reading worked
 if (l.error != 0) {
  fprintf(stderr, "Error: str_redfile() error: '%d'\n", l.error);
  fclose(f);
  exit(l.error);
 }

 // dump file infos
 str_dump(&l);

 // TODO: deallocate the memory
 // free memory
 //free(l.text);

 exit(EXIT_SUCCESS);
}

compiling the shared library and the test program from a bash:

#!/usr/bin/env bash
#
# gcc, compile a shared object file
#
# This example shows how to compile a shared object for C with gcc on linux. 
# required files: string.c, string.h test.
#
# $Id$

# configuration
bin=test
libname=string
v[0]=1; v[1]=0; v[2]=1;

# dynamic library
rm lib$libname* $bin
gcc -c -fPIC $libname.c -o $libname.o
gcc -shared -Wl,-soname,lib$libname.so -o lib$libname.so $libname.o
# create links for ld
#ln -s lib$libname.so lib$libname.so.${v[0]}
#ln -s lib$libname.so.${v[0]} lib$libname.so.${v[0]}.${v[1]}
#ln -s lib$libname.so.${v[0]}.${v[1]} lib$libname.so.${v[0]}.${v[1]}.${v[2]}

# compile executable
gcc $bin.c -o $bin -L. -l$libname

# run with proper LD_LIBRARY env variable, example:
# $ LD_LIBRARY_PATH=. ./test [path-to-file]

Running the executable. Make the newly compiled library available to ld through an environment variable.

$ LD_LIBRARY_PATH=. ./test [path-to-file]