From 86df5cd1a918fcd88e494ba2d4367518cd8f4224 Mon Sep 17 00:00:00 2001 From: Leandro Silva Date: Sun, 3 Jan 2021 12:56:55 -0300 Subject: [PATCH] examples: C interop for HTML to PDF conversion using libwkhtmltox (#7751) --- .github/workflows/ci.yml | 4 ++ cmd/tools/modules/testing/common.v | 5 ++ examples/wkhtmltopdf.v | 94 ++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 examples/wkhtmltopdf.v diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 91685d1692..254b3a5a1c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -80,6 +80,10 @@ jobs: sudo apt-get install --quiet -y libssl-dev sqlite3 libsqlite3-dev valgrind sudo apt-get install --quiet -y libglfw3 libglfw3-dev libfreetype6-dev libxi-dev libxcursor-dev libasound2-dev ## sudo apt-get install --quiet -y libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libsdl2-image-dev + ## The following is needed for examples/wkhtmltopdf.v + wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb + sudo apt-get install xfonts-75dpi xfonts-base + sudo dpkg -i wkhtmltox_0.12.6-1.focal_amd64.deb - name: Build v run: | echo $VFLAGS diff --git a/cmd/tools/modules/testing/common.v b/cmd/tools/modules/testing/common.v index 93f87f9222..8617593a0e 100644 --- a/cmd/tools/modules/testing/common.v +++ b/cmd/tools/modules/testing/common.v @@ -8,6 +8,8 @@ import sync import v.pref import v.util.vtest +const github_job = os.getenv('GITHUB_JOB') + pub struct TestSession { pub mut: files []string @@ -113,6 +115,9 @@ pub fn new_test_session(_vargs string) TestSession { $if windows { skip_files << 'examples/x/websocket/ping.v' // requires OpenSSL } + if github_job != 'ubuntu-tcc' { + skip_files << 'examples/wkhtmltopdf.v' // needs installation of wkhtmltopdf from https://github.com/wkhtmltopdf/packaging/releases + } vargs := _vargs.replace('-progress', '').replace('-progress', '') vexe := pref.vexe_path() new_vtmp_dir := setup_new_vtmp_folder() diff --git a/examples/wkhtmltopdf.v b/examples/wkhtmltopdf.v new file mode 100644 index 0000000000..1d92a33d69 --- /dev/null +++ b/examples/wkhtmltopdf.v @@ -0,0 +1,94 @@ +import os + +// Example of C interop for a very handy task. +// +// wkhtmltopdf and wkhtmltoimage are open source (LGPLv3) command line tools to +// render HTML into PDF and various image formats using the Qt WebKit rendering +// engine. These run entirely "headless" and do not require a display or display +// service. +// +// https://github.com/wkhtmltopdf/wkhtmltopdf +// https://wkhtmltopdf.org/downloads.html +// https://wkhtmltopdf.org/libwkhtmltox/ +#flag -lwkhtmltox +#include "wkhtmltox/pdf.h" # You can install the C package for your system from the wkhtmltopdf.org/downloads.html page +struct C.wkhtmltopdf_global_settings {} + +struct C.wkhtmltopdf_object_settings {} + +struct C.wkhtmltopdf_converter {} + +fn C.wkhtmltopdf_init(use_graphics bool) int + +fn C.wkhtmltopdf_deinit() int + +fn C.wkhtmltopdf_version() charptr + +fn C.wkhtmltopdf_create_global_settings() &C.wkhtmltopdf_global_settings + +fn C.wkhtmltopdf_destroy_global_settings(global_settings &C.wkhtmltopdf_global_settings) + +fn wkhtmltopdf_set_global_setting(global_settings &C.wkhtmltopdf_global_settings, name charptr, value charptr) bool + +fn C.wkhtmltopdf_create_object_settings() &C.wkhtmltopdf_object_settings + +fn C.wkhtmltopdf_destroy_object_settings(object_settings &C.wkhtmltopdf_object_settings) + +fn C.wkhtmltopdf_set_object_setting(object_settings &C.wkhtmltopdf_object_settings, name charptr, value charptr) bool + +fn C.wkhtmltopdf_create_converter(global_settings &C.wkhtmltopdf_global_settings) &C.wkhtmltopdf_converter + +fn C.wkhtmltopdf_destroy_converter(converter &C.wkhtmltopdf_converter) + +fn C.wkhtmltopdf_add_object(converter &C.wkhtmltopdf_converter, object_settings &C.wkhtmltopdf_object_settings, data charptr) + +fn C.wkhtmltopdf_convert(converter &C.wkhtmltopdf_converter) bool + +fn C.wkhtmltopdf_http_error_code(converter &C.wkhtmltopdf_converter) int + +fn C.wkhtmltopdf_get_output(converter &C.wkhtmltopdf_converter, data &charptr) int + +fn main() { + // init + init := C.wkhtmltopdf_init(0) + println('wkhtmltopdf_init: $init') + version := C.wkhtmltopdf_version() + println('wkhtmltopdf_version: $version') + global_settings := C.wkhtmltopdf_create_global_settings() + println('wkhtmltopdf_create_global_settings: ${voidptr(global_settings)}') + object_settings := C.wkhtmltopdf_create_object_settings() + println('wkhtmltopdf_create_object_settings') + converter := C.wkhtmltopdf_create_converter(global_settings) + println('wkhtmltopdf_create_converter: ${voidptr(converter)}') + // convert + mut result := C.wkhtmltopdf_set_object_setting(object_settings, 'page', 'http://www.google.com.br') + println('wkhtmltopdf_set_object_setting: $result [page = http://www.google.com.br]') + C.wkhtmltopdf_add_object(converter, object_settings, 0) + println('wkhtmltopdf_add_object') + result = C.wkhtmltopdf_convert(converter) + println('wkhtmltopdf_convert: $result') + error_code := C.wkhtmltopdf_http_error_code(converter) + println('wkhtmltopdf_http_error_code: $error_code') + if result { + data := &charptr(0) + size := C.wkhtmltopdf_get_output(converter, &data) + println('wkhtmltopdf_get_output: $size bytes') + mut file := os.open_file('./google.pdf', 'w+', 0o666) or { + println('ERR: $err') + return + } + wrote := file.write_bytes(data, size) + println('write_bytes: $wrote [./google.pdf]') + file.flush() + file.close() + } + // destroy + C.wkhtmltopdf_destroy_converter(converter) + println('wkhtmltopdf_destroy_converter') + C.wkhtmltopdf_destroy_object_settings(object_settings) + println('wkhtmltopdf_destroy_object_settings: ${voidptr(object_settings)}') + C.wkhtmltopdf_destroy_global_settings(global_settings) + println('wkhtmltopdf_destroy_global_settings') + deinit := C.wkhtmltopdf_deinit() + println('wkhtmltopdf_deinit: $deinit') +}