Add support for external shared object renderer

This commit is contained in:
Mario Hüttel 2018-12-15 00:05:34 +01:00
parent f025a0233d
commit f54ff7ded6
6 changed files with 164 additions and 17 deletions

View File

@ -19,7 +19,7 @@ aux_source_directory("gds-parser" PARSER_SOURCES)
aux_source_directory("latex-output" LATEX_SOURCES) aux_source_directory("latex-output" LATEX_SOURCES)
aux_source_directory("cairo-output" CAIRO_SOURCES) aux_source_directory("cairo-output" CAIRO_SOURCES)
aux_source_directory("trigonometric" TRIG_SOURCES) aux_source_directory("trigonometric" TRIG_SOURCES)
set(SOURCE "main.c" "layer-selector.c" "mapping-parser.c" "command-line.c" "main-window.c") set(SOURCE "main.c" "layer-selector.c" "mapping-parser.c" "command-line.c" "main-window.c" "external-renderer.c")
set(SOURCE set(SOURCE
${SOURCE} ${SOURCE}
@ -36,6 +36,6 @@ add_compile_options(-Wall)
add_executable(${PROJECT_NAME} ${SOURCE} ${CMAKE_CURRENT_BINARY_DIR}/glade/resources.c) add_executable(${PROJECT_NAME} ${SOURCE} ${CMAKE_CURRENT_BINARY_DIR}/glade/resources.c)
add_dependencies(${PROJECT_NAME} glib-resources) add_dependencies(${PROJECT_NAME} glib-resources)
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/glade/resources.c PROPERTIES GENERATED 1) SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/glade/resources.c PROPERTIES GENERATED 1)
target_link_libraries(${PROJECT_NAME} ${GLIB_LDFLAGS} ${GTK3_LDFLAGS} ${CAIRO_LDFLAGS} m) target_link_libraries(${PROJECT_NAME} ${GLIB_LDFLAGS} ${GTK3_LDFLAGS} ${CAIRO_LDFLAGS} m ${CMAKE_DL_LIBS})
install (TARGETS ${PROJECT_NAME} DESTINATION bin) install (TARGETS ${PROJECT_NAME} DESTINATION bin)

View File

@ -34,6 +34,7 @@
#include "mapping-parser.h" #include "mapping-parser.h"
#include "cairo-output/cairo-output.h" #include "cairo-output/cairo-output.h"
#include "latex-output/latex-output.h" #include "latex-output/latex-output.h"
#include "external-renderer.h"
/** /**
* @brief Delete layer_info and free nem element. * @brief Delete layer_info and free nem element.
@ -52,7 +53,7 @@ static void delete_layer_info_with_name(struct layer_info *info)
void command_line_convert_gds(char *gds_name, char *pdf_name, char *tex_name, gboolean pdf, gboolean tex, void command_line_convert_gds(char *gds_name, char *pdf_name, char *tex_name, gboolean pdf, gboolean tex,
char *layer_file, char *cell_name, double scale, gboolean pdf_layers, char *layer_file, char *cell_name, double scale, gboolean pdf_layers,
gboolean pdf_standalone, gboolean svg, char *svg_name) gboolean pdf_standalone, gboolean svg, char *svg_name, char *so_name, char *so_out_file)
{ {
GList *libs = NULL; GList *libs = NULL;
FILE *tex_file; FILE *tex_file;
@ -71,7 +72,7 @@ void command_line_convert_gds(char *gds_name, char *pdf_name, char *tex_name, gb
struct gds_cell *toplevel_cell = NULL, *temp_cell; struct gds_cell *toplevel_cell = NULL, *temp_cell;
/* Check if parameters are valid */ /* Check if parameters are valid */
if (!gds_name || ! pdf_name || !tex_name || !layer_file || !cell_name) { if (!gds_name || (!pdf_name && pdf) || (!tex_name && tex) || !layer_file || !cell_name) {
printf("Probably missing argument. Check --help option\n"); printf("Probably missing argument. Check --help option\n");
return; return;
} }
@ -144,6 +145,16 @@ void command_line_convert_gds(char *gds_name, char *pdf_name, char *tex_name, gb
fclose(tex_file); fclose(tex_file);
} }
if (so_name && so_out_file) {
if (strlen(so_name) == 0 || strlen(so_out_file) == 0)
goto ret_clear_list;
/* Render output using external renderer */
printf("Invoking external renderer!\n");
external_renderer_render_cell(toplevel_cell, layer_info_list, so_out_file, so_name);
printf("External renderer finished!\n");
}
ret_clear_list: ret_clear_list:
g_list_free_full(layer_info_list, (GDestroyNotify)delete_layer_info_with_name); g_list_free_full(layer_info_list, (GDestroyNotify)delete_layer_info_with_name);

View File

@ -45,11 +45,13 @@
* @param pdf_layers TikZ creates OCG layers * @param pdf_layers TikZ creates OCG layers
* @param pdf_standalone LaTeX document is standalone7 * @param pdf_standalone LaTeX document is standalone7
* @param svg Render to SVG file * @param svg Render to SVG file
* @param so_name Path to shared object of custom renderer
* @param so_out_file Output file path for custom renderer
* @param svg_name SVG file name * @param svg_name SVG file name
*/ */
void command_line_convert_gds(char *gds_name, char *pdf_name, char *tex_name, gboolean pdf, gboolean tex, void command_line_convert_gds(char *gds_name, char *pdf_name, char *tex_name, gboolean pdf, gboolean tex,
char *layer_file, char *cell_name, double scale, gboolean pdf_layers, char *layer_file, char *cell_name, double scale, gboolean pdf_layers,
gboolean pdf_standalone, gboolean svg, char *svg_name); gboolean pdf_standalone, gboolean svg, char *svg_name, char *so_name, char *so_out_file);
#endif /* _COMMAND_LINE_H_ */ #endif /* _COMMAND_LINE_H_ */

70
external-renderer.c Normal file
View File

@ -0,0 +1,70 @@
/*
* GDSII-Converter
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of GDSII-Converter.
*
* GDSII-Converter is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* GDSII-Converter is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file external-renderer.c
* @brief This file implements the dynamic library loading for the external rendering feature
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
/**
* @addtogroup MainApplication
* @{
*/
#include "external-renderer.h"
#include <dlfcn.h>
#include <stdio.h>
int external_renderer_render_cell(struct gds_cell *toplevel_cell, GList *layer_info_list, char *output_file, char *so_path)
{
int (*so_render_func)(struct gds_cell *, GList *, char *) = NULL;
void *so_handle = NULL;
char *error_msg;
int ret = 0;
/* Check parameter sanity */
if (!output_file || !so_path || !toplevel_cell || !layer_info_list) {
return -3000;
}
/* Load shared object */
so_handle = dlopen(so_path, RTLD_LAZY);
if (!so_handle) {
printf("Could not load external library '%s'\nDetailed error is:\n%s\n", so_path, dlerror());
return -2000;
}
/* Load symbol from library */
so_render_func = (int (*)(struct gds_cell *, GList *, char *))dlsym(so_handle, EXTERNAL_LIBRARY_FUNCTION);
if ((error_msg = dlerror()) != NULL) {
printf("Rendering function not found in library:\n%s\n", error_msg);
goto ret_close_so_handle;
}
/* Execute */
if (so_render_func)
so_render_func(toplevel_cell, layer_info_list, output_file);
ret_close_so_handle:
dlclose(so_handle);
return ret;
}
/** @} */

58
external-renderer.h Normal file
View File

@ -0,0 +1,58 @@
/*
* GDSII-Converter
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of GDSII-Converter.
*
* GDSII-Converter is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* GDSII-Converter is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file command-line.c
* @brief Render according to command line parameters
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
/**
* @addtogroup MainApplication
* @{
*/
#ifndef _EXTERNAL_RENDERER_H_
#define _EXTERNAL_RENDERER_H_
#include "gds-parser/gds-types.h"
#include <glib.h>
/**
* @brief function name expected to be found in external library.
* @detail The function has to be defined as follows:
* @code
* int function_name(gds_cell *toplevel, GList *layer_info_list, char *output_file_name)
* @endcode
*/
#define EXTERNAL_LIBRARY_FUNCTION "render_cell_to_file"
/**
* @brief external_renderer_render_cell
* @param toplevel_cell The toplevel cell to render
* @param layer_info_list The layer information. Contains #layer_info elements
* @param output_file Output file
* @param so_path Path to the shared object file containing #EXTERNAL_LIBRARY_FUNCTION
* @return 0 on success
*/
int external_renderer_render_cell(struct gds_cell *toplevel_cell, GList *layer_info_list, char *output_file, char *so_path);
#endif /* _EXTERNAL_RENDERER_H_ */
/** @} */

30
main.c
View File

@ -22,6 +22,7 @@
#include <glib.h> #include <glib.h>
#include "main-window.h" #include "main-window.h"
#include "command-line.h" #include "command-line.h"
#include "external-renderer.h"
struct application_data { struct application_data {
GtkApplication *app; GtkApplication *app;
@ -116,22 +117,26 @@ int main(int argc, char **argv)
gchar *basename; gchar *basename;
gchar *pdfname = NULL, *texname = NULL, *mappingname = NULL, *cellname = NULL, *svgname = NULL; gchar *pdfname = NULL, *texname = NULL, *mappingname = NULL, *cellname = NULL, *svgname = NULL;
gboolean tikz = FALSE, pdf = FALSE, pdf_layers = FALSE, pdf_standalone = FALSE, svg = FALSE; gboolean tikz = FALSE, pdf = FALSE, pdf_layers = FALSE, pdf_standalone = FALSE, svg = FALSE;
gchar *custom_library_path = NULL;
gchar *custom_library_file_name = NULL;
int scale = 1000; int scale = 1000;
int app_status; int app_status;
GOptionEntry entries[] = { GOptionEntry entries[] = {
{ "tikz", 't', 0, G_OPTION_ARG_NONE, &tikz, "Output TikZ code", NULL }, {"tikz", 't', 0, G_OPTION_ARG_NONE, &tikz, "Output TikZ code", NULL },
{ "pdf", 'p', 0, G_OPTION_ARG_NONE, &pdf, "Output PDF document", NULL }, {"pdf", 'p', 0, G_OPTION_ARG_NONE, &pdf, "Output PDF document", NULL },
//{ "svg", 'S', 0, G_OPTION_ARG_NONE, &svg, "Output SVG image", NULL }, //{"svg", 'S', 0, G_OPTION_ARG_NONE, &svg, "Output SVG image", NULL },
{ "scale", 's', 0, G_OPTION_ARG_INT, &scale, "Divide output coordinates by <SCALE>", "<SCALE>" }, {"scale", 's', 0, G_OPTION_ARG_INT, &scale, "Divide output coordinates by <SCALE>", "<SCALE>" },
{ "tex-output", 'o', 0, G_OPTION_ARG_FILENAME, &texname, "Optional path for TeX file", "PATH" }, {"tex-output", 'o', 0, G_OPTION_ARG_FILENAME, &texname, "Optional path for TeX file", "PATH" },
{ "pdf-output", 'O', 0, G_OPTION_ARG_FILENAME, &pdfname, "Optional path for PDF file", "PATH" }, {"pdf-output", 'O', 0, G_OPTION_ARG_FILENAME, &pdfname, "Optional path for PDF file", "PATH" },
//{ "svg-output", 0, 0, G_OPTION_ARG_FILENAME, &svgname, "Optional path for PDF file", "PATH"}, //{"svg-output", 0, 0, G_OPTION_ARG_FILENAME, &svgname, "Optional path for PDF file", "PATH"},
{ "mapping", 'm', 0, G_OPTION_ARG_FILENAME, &mappingname, "Path for Layer Mapping File", "PATH" }, {"mapping", 'm', 0, G_OPTION_ARG_FILENAME, &mappingname, "Path for Layer Mapping File", "PATH" },
{ "cell", 'c', 0, G_OPTION_ARG_STRING, &cellname, "Cell to render", "NAME" }, {"cell", 'c', 0, G_OPTION_ARG_STRING, &cellname, "Cell to render", "NAME" },
{ "tex-standalone", 'a', 0, G_OPTION_ARG_NONE, &pdf_standalone, "Create standalone PDF", NULL }, {"tex-standalone", 'a', 0, G_OPTION_ARG_NONE, &pdf_standalone, "Create standalone PDF", NULL },
{ "tex-layers", 'l', 0, G_OPTION_ARG_NONE, &pdf_layers, "Create PDF Layers (OCG)", NULL }, {"tex-layers", 'l', 0, G_OPTION_ARG_NONE, &pdf_layers, "Create PDF Layers (OCG)", NULL },
{"custom-render-lib", 'P', 0, G_OPTION_ARG_FILENAME, &custom_library_path, "Path to a custom shared object, that implements the " EXTERNAL_LIBRARY_FUNCTION " function", "PATH"},
{"external-lib-output", 'e', 0, G_OPTION_ARG_FILENAME, &custom_library_file_name, "Output path for external render library", "PATH"},
{ NULL } { NULL }
}; };
@ -171,7 +176,8 @@ int main(int argc, char **argv)
command_line_convert_gds(gds_name, pdfname, texname, pdf, tikz, command_line_convert_gds(gds_name, pdfname, texname, pdf, tikz,
mappingname, cellname, (double)scale, mappingname, cellname, (double)scale,
pdf_layers, pdf_standalone, svg, svgname); pdf_layers, pdf_standalone, svg, svgname,
custom_library_path, custom_library_file_name);
/* Clean up */ /* Clean up */
g_free(pdfname); g_free(pdfname);
g_free(texname); g_free(texname);