Permalink
Browse files

Use libtool and dlopen().

  • Loading branch information...
schmonz committed Jul 27, 2017
1 parent ab91c18 commit abd639901f47c6b0e23fff0fd0a73b1b2a1a8fe7
Showing with 87 additions and 113 deletions.
  1. +41 −17 GNUmakefile
  2. +3 −3 check_mandelbrot.c
  3. +25 −16 graph.c
  4. +6 −13 graph_cairo.c
  5. +0 −12 graph_cairo.h
  6. +6 −14 graph_gd.c
  7. +0 −12 graph_gd.h
  8. +6 −14 graph_imlib2.c
  9. +0 −12 graph_imlib2.h
View
@@ -1,14 +1,18 @@
SILENT ?= @
LIBTOOL_SILENT ?= >/dev/null 2>&1
BACKEND ?= gd
OUTPUTFILE ?= pngelbrot.png
APPROVAL_TESTS = approve_mandelbrot
THE_TESTS = check_mandelbrot
THE_LIBRARY = mandelbrot.a
THE_PROGRAM = main
DESTDIR ?= /Users/schmonz/Documents/trees/c-mandelbrot
RPATH ?= /opt/pkg/lib
LIBTOOL ?= /opt/pkg/bin/libtool ${LIBTOOL_SILENT}
CFLAGS += -g -O0 -Wall -Werror -Wextra -std=c99
LIBS += -lm
LIBS += -ldl -lm
CAIRO_CFLAGS := $(shell pkg-config --cflags cairo 2>/dev/null)
CAIRO_LIBS := $(shell pkg-config --libs cairo 2>/dev/null)
CHECK_CFLAGS := $(shell pkg-config --cflags check 2>/dev/null)
@@ -27,18 +31,20 @@ all: check approval
check: ${THE_TESTS}
${SILENT}./${THE_TESTS}
approval: .has_imagemagick ${THE_PROGRAM}
${SILENT}./${THE_PROGRAM} ${BACKEND} ${OUTPUTFILE} 800 500 100 0.0 0.0 4.0
approval: .has_imagemagick ${THE_PROGRAM} graph_${BACKEND}.so
${SILENT}./${THE_PROGRAM} graph_${BACKEND}.so ${OUTPUTFILE} 800 500 100 0.0 0.0 4.0
${SILENT}./${APPROVAL_TESTS} ${OUTPUTFILE}
valgrind: ${THE_TESTS}
${SILENT}valgrind --leak-check=full --show-leak-kinds=all ./${THE_TESTS}
clean:
${SILENT}rm -f .has_* *.o ${THE_TESTS} ${THE_LIBRARY} ${THE_PROGRAM}
${SILENT}rm -rf *.dSYM
${SILENT}rm -f .has_* *.o *.lo *.la *.so ${THE_TESTS} ${THE_LIBRARY} ${THE_PROGRAM}
${SILENT}rm -rf *.dSYM .libs
.PHONY: all check approval valgrind clean
modules: graph_cairo.so graph_gd.so graph_imlib2.so
.PHONY: all check approval valgrind clean modules
.has_cairo:
ifeq (, ${CAIRO_LIBS})
@@ -82,20 +88,38 @@ else
${SILENT}touch .has_mpc
endif
check_mandelbrot.o: .has_check mandelbrot.h mandelbrot.c
check_mandelbrot.o: .has_check mandelbrot.h mandelbrot.c check_mandelbrot.c
${SILENT}${CC} ${CFLAGS} ${CHECK_CFLAGS} -c check_mandelbrot.c
graph.o: graph.h graph.c
${SILENT}${CC} ${CFLAGS} -c graph.c
graph_cairo.o: .has_cairo graph.h graph_cairo.h graph_cairo.c
${SILENT}${CC} ${CFLAGS} ${CAIRO_CFLAGS} -c graph_cairo.c
graph_cairo.lo: .has_cairo graph.h graph_cairo.c
${SILENT}${LIBTOOL} --mode=compile --tag=CC ${CC} ${CFLAGS} ${CAIRO_CFLAGS} -c graph_cairo.c
graph_cairo.la: graph_cairo.lo
${SILENT}${LIBTOOL} --mode=link --tag=CC ${CC} -module ${LDFLAGS} ${CAIRO_LIBS} -o graph_cairo.la graph_cairo.lo -version-info 0:0:0 -rpath ${RPATH}
graph_cairo.so: graph_cairo.la
${SILENT}${LIBTOOL} --mode=install install -c .libs/graph_cairo.so ${DESTDIR}/graph_cairo.so
graph_gd.lo: .has_gd graph.h graph_gd.c
${SILENT}${LIBTOOL} --mode=compile --tag=CC ${CC} ${CFLAGS} ${GD_CFLAGS} -c graph_gd.c
graph_gd.la: graph_gd.lo
${SILENT}${LIBTOOL} --mode=link --tag=CC ${CC} -module ${LDFLAGS} ${GD_LIBS} -o graph_gd.la graph_gd.lo -version-info 0:0:0 -rpath ${RPATH}
graph_gd.so: graph_gd.la
${SILENT}${LIBTOOL} --mode=install install -c .libs/graph_gd.so ${DESTDIR}/graph_gd.so
graph_imlib2.lo: .has_imlib2 graph.h graph_imlib2.c
${SILENT}${LIBTOOL} --mode=compile --tag=CC ${CC} ${CFLAGS} ${IMLIB2_CFLAGS} -c graph_imlib2.c
graph_gd.o: .has_gd graph.h graph_gd.h graph_gd.c
${SILENT}${CC} ${CFLAGS} ${GD_CFLAGS} -c graph_gd.c
graph_imlib2.la: graph_imlib2.lo
${SILENT}${LIBTOOL} --mode=link --tag=CC ${CC} -module ${LDFLAGS} ${IMLIB2_LIBS} -o graph_imlib2.la graph_imlib2.lo -version-info 0:0:0 -rpath ${RPATH}
graph_imlib2.o: .has_imlib2 graph.h graph_imlib2.h graph_imlib2.c
${SILENT}${CC} ${CFLAGS} ${IMLIB2_CFLAGS} -c graph_imlib2.c
graph_imlib2.so: graph_imlib2.la
${SILENT}${LIBTOOL} --mode=install install -c .libs/graph_imlib2.so ${DESTDIR}/graph_imlib2.so
main.o: mandelbrot.h main.c
${SILENT}${CC} ${CFLAGS} -c main.c
@@ -107,11 +131,11 @@ mandelbrot_mpc.o: .has_mpc mandelbrot.h mandelbrot_mpc.c
${SILENT}${CC} ${CFLAGS} ${MPC_CFLAGS} -c mandelbrot_mpc.c
${THE_TESTS}: ${THE_LIBRARY} check_mandelbrot.o
${SILENT}${CC} ${LDFLAGS} ${THE_LIBRARY} ${LIBS} ${CAIRO_LIBS} ${GD_LIBS} ${IMLIB2_LIBS} ${MPC_LIBS} ${CHECK_LIBS} check_mandelbrot.o -o ${THE_TESTS}
${SILENT}${CC} ${LDFLAGS} ${THE_LIBRARY} ${LIBS} ${MPC_LIBS} ${CHECK_LIBS} check_mandelbrot.o -o ${THE_TESTS}
${THE_LIBRARY}: graph.o graph_cairo.o graph_gd.o graph_imlib2.o mandelbrot.o mandelbrot_mpc.o
${SILENT}ar rc ${THE_LIBRARY} graph.o graph_cairo.o graph_gd.o graph_imlib2.o mandelbrot.o mandelbrot_mpc.o
${THE_LIBRARY}: modules graph.o mandelbrot.o mandelbrot_mpc.o
${SILENT}ar rc ${THE_LIBRARY} graph.o mandelbrot.o mandelbrot_mpc.o
${SILENT}ranlib ${THE_LIBRARY}
${THE_PROGRAM}: ${THE_LIBRARY} main.o
${SILENT}${CC} ${LDFLAGS} ${THE_LIBRARY} ${LIBS} ${CAIRO_LIBS} ${GD_LIBS} ${IMLIB2_LIBS} ${MPC_LIBS} main.o -o ${THE_PROGRAM}
${SILENT}${CC} ${LDFLAGS} ${THE_LIBRARY} ${LIBS} main.o -o ${THE_PROGRAM}
View
@@ -44,7 +44,7 @@ START_TEST(test_complex_plane_coordinates)
{
const int width = 800, height = width;
graph_t graph = graph_create("", width, height, 0 + I * 0, 4.0);
graph_t graph = graph_create("graph_gd.so", width, height, 0 + I * 0, 4.0);
assert_complex_points_equal(-2 - I * 2, graph.extremes.lower_left);
assert_complex_points_equal( 2 + I * 2, graph.extremes.upper_right);
@@ -62,7 +62,7 @@ START_TEST(test_aspect_ratio_in_portrait)
{
const int width = 500, height = 800;
graph_t graph = graph_create("", width, height, 0.25 + I * -0.3, 2.0);
graph_t graph = graph_create("graph_gd.so", width, height, 0.25 + I * -0.3, 2.0);
assert_complex_points_equal(-0.375 - I * 1.3, graph.extremes.lower_left);
assert_complex_points_equal( 0.875 + I * 0.7, graph.extremes.upper_right);
@@ -75,7 +75,7 @@ START_TEST(test_aspect_ratio_in_landscape)
{
const int width = 600, height = 450;
graph_t graph = graph_create("", width, height, -0.25 + I * 0.3, 4.0);
graph_t graph = graph_create("graph_gd.so", width, height, -0.25 + I * 0.3, 4.0);
assert_complex_points_equal(-2.25 - I * 1.2, graph.extremes.lower_left);
assert_complex_points_equal( 1.75 + I * 1.8, graph.extremes.upper_right);
View
41 graph.c
@@ -1,27 +1,35 @@
#include <dlfcn.h>
#include <string.h>
#include <unistd.h>
#include "graph.h"
#include "graph_cairo.h"
#include "graph_gd.h"
#include "graph_imlib2.h"
static void *graph_backend_module;
static graph_backend_t graph_backend;
static void
graph_backend_create(graph_t *graph, const char *desired_graph_backend)
static void *dlopen_or_die(const char *modulepath)
{
void *actual = dlopen(modulepath, RTLD_LAZY);
if (!actual) _exit(77);
return actual;
}
static void *dlsym_or_die(void *module, const char *symbol)
{
const size_t NUM_BACKENDS = 3;
graph_backend_t graph_backends[NUM_BACKENDS];
void *actual = dlsym(module, symbol);
if (!actual) _exit(88);
return actual;
}
graph_backends[0] = graph_backend_cairo;
graph_backends[1] = graph_backend_imlib2;
graph_backends[2] = graph_backend_gd;
static void
graph_backend_init(graph_t *graph, const char *desired_graph_backend)
{
graph_backend_module = dlopen_or_die(desired_graph_backend);
for (size_t i = 0; i < NUM_BACKENDS; i++) {
graph_backend = graph_backends[i];
if (0 == strcmp(graph_backend.name, desired_graph_backend))
break;
}
graph_backend.create = dlsym_or_die(graph_backend_module, "graph_backend_create");
graph_backend.set_pixel = dlsym_or_die(graph_backend_module, "graph_backend_set_pixel");
graph_backend.write = dlsym_or_die(graph_backend_module, "graph_backend_write");
graph_backend.destroy = dlsym_or_die(graph_backend_module, "graph_backend_destroy");
graph_backend.create(graph);
}
@@ -46,7 +54,7 @@ graph_create(const char *desired_graph_backend,
},
};
graph_backend_create(&graph, desired_graph_backend);
graph_backend_init(&graph, desired_graph_backend);
return graph;
}
@@ -110,4 +118,5 @@ void
graph_destroy(const graph_t graph)
{
graph_backend.destroy(graph);
dlclose(graph_backend_module);
}
View
@@ -1,8 +1,9 @@
#include <cairo/cairo.h>
#include "graph_cairo.h"
#include "graph.h"
void
graph_backend_cairo_create(graph_t *graph)
graph_backend_create(graph_t *graph)
{
graph->image = cairo_create(
cairo_image_surface_create(CAIRO_FORMAT_RGB24,
@@ -11,7 +12,7 @@ graph_backend_cairo_create(graph_t *graph)
}
void
graph_backend_cairo_set_pixel(const graph_t graph,
graph_backend_set_pixel(const graph_t graph,
const size_t horizontal, const size_t vertical,
const size_t colormap_entry)
{
@@ -24,22 +25,14 @@ graph_backend_cairo_set_pixel(const graph_t graph,
}
void
graph_backend_cairo_write(const graph_t graph, const char *outputfile)
graph_backend_write(const graph_t graph, const char *outputfile)
{
cairo_surface_write_to_png(cairo_get_target(graph.image), outputfile);
}
void
graph_backend_cairo_destroy(const graph_t graph)
graph_backend_destroy(const graph_t graph)
{
cairo_surface_destroy(cairo_get_target(graph.image));
cairo_destroy(graph.image);
}
graph_backend_t graph_backend_cairo = {
"cairo",
graph_backend_cairo_create,
graph_backend_cairo_set_pixel,
graph_backend_cairo_write,
graph_backend_cairo_destroy,
};
View
@@ -1,12 +0,0 @@
#include "graph.h"
void graph_backend_cairo_create(graph_t *);
void graph_backend_cairo_set_pixel(const graph_t,
const size_t, const size_t, const size_t);
void graph_backend_cairo_write(const graph_t, const char *);
void graph_backend_cairo_destroy(const graph_t);
graph_backend_t graph_backend_cairo;
View
@@ -1,8 +1,9 @@
#include <gd.h>
#include "graph_gd.h"
#include "graph.h"
void
graph_backend_gd_create(graph_t *graph)
graph_backend_create(graph_t *graph)
{
graph->image = gdImageCreate(graph->width, graph->height);
for (size_t i = 0; i < NUM_COLORS; i++) {
@@ -14,32 +15,23 @@ graph_backend_gd_create(graph_t *graph)
}
void
graph_backend_gd_set_pixel(const graph_t graph,
graph_backend_set_pixel(const graph_t graph,
const size_t horizontal, const size_t vertical,
const size_t colormap_entry)
{
gdImageSetPixel(graph.image, horizontal, vertical, colormap_entry);
}
void
graph_backend_gd_write(const graph_t graph, const char *outputfile)
graph_backend_write(const graph_t graph, const char *outputfile)
{
FILE *pngout = fopen(outputfile, "wb");
gdImagePng(graph.image, pngout);
fclose(pngout);
}
void
graph_backend_gd_destroy(const graph_t graph)
graph_backend_destroy(const graph_t graph)
{
gdImageDestroy(graph.image);
}
graph_backend_t graph_backend_gd = {
"gd",
graph_backend_gd_create,
graph_backend_gd_set_pixel,
graph_backend_gd_write,
graph_backend_gd_destroy,
};
View
@@ -1,12 +0,0 @@
#include "graph.h"
void graph_backend_gd_create(graph_t *);
void graph_backend_gd_set_pixel(const graph_t,
const size_t, const size_t, const size_t);
void graph_backend_gd_write(const graph_t, const char *);
void graph_backend_gd_destroy(const graph_t);
graph_backend_t graph_backend_gd;
View
@@ -1,15 +1,16 @@
#include <Imlib2.h>
#include "graph_imlib2.h"
#include "graph.h"
void
graph_backend_imlib2_create(graph_t *graph)
graph_backend_create(graph_t *graph)
{
graph->image = imlib_create_image(graph->width, graph->height);
imlib_context_set_image(graph->image);
}
void
graph_backend_imlib2_set_pixel(const graph_t graph,
graph_backend_set_pixel(const graph_t graph,
const size_t horizontal, const size_t vertical,
const size_t colormap_entry)
{
@@ -22,25 +23,16 @@ graph_backend_imlib2_set_pixel(const graph_t graph,
}
void
graph_backend_imlib2_write(const graph_t graph, const char *outputfile)
graph_backend_write(const graph_t graph, const char *outputfile)
{
(void)graph;
imlib_image_set_format("png");
imlib_save_image(outputfile);
}
void
graph_backend_imlib2_destroy(const graph_t graph)
graph_backend_destroy(const graph_t graph)
{
(void)graph;
imlib_free_image();
}
graph_backend_t graph_backend_imlib2 = {
"imlib2",
graph_backend_imlib2_create,
graph_backend_imlib2_set_pixel,
graph_backend_imlib2_write,
graph_backend_imlib2_destroy,
};
View
@@ -1,12 +0,0 @@
#include "graph.h"
void graph_backend_imlib2_create(graph_t *);
void graph_backend_imlib2_set_pixel(const graph_t,
const size_t, const size_t, const size_t);
void graph_backend_imlib2_write(const graph_t, const char *);
void graph_backend_imlib2_destroy(const graph_t);
graph_backend_t graph_backend_imlib2;

0 comments on commit abd6399

Please sign in to comment.