├── README.md
├── .gitignore
├── test.go
└── wkhtmltopdf
└── pdf_c_api.go
/README.md:
--------------------------------------------------------------------------------
1 | Depends on wkhtmltopdf library
2 | http://wkhtmltopdf.org/downloads.html
3 |
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Example user template template
3 | ### Example user template
4 |
5 | # IntelliJ project files
6 | .idea
7 | *.iml
8 | test.pdf
9 | .DS_Store
--------------------------------------------------------------------------------
/test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "./wkhtmltopdf"
5 | "fmt"
6 | "io/ioutil"
7 | )
8 |
9 | func main() {
10 | // global settings: http://www.cs.au.dk/~jakobt/libwkhtmltox_0.10.0_doc/pagesettings.html#pagePdfGlobal
11 | gs := wkhtmltopdf.NewGlobalSettings()
12 | gs.Set("outputFormat", "pdf")
13 | gs.Set("out", "")
14 | gs.Set("orientation", "Portrait")
15 | gs.Set("colorMode", "Color")
16 | gs.Set("size.paperSize", "A4")
17 | //gs.Set("load.cookieJar", "myjar.jar")
18 | // object settings: http://www.cs.au.dk/~jakobt/libwkhtmltox_0.10.0_doc/pagesettings.html#pagePdfObject
19 | objset := wkhtmltopdf.NewObjectSettings()
20 | objset.Set("page", "http://www.slashdot.org")
21 | objset.Set("load.debugJavascript", "false")
22 | //os.Set("load.jsdelay", "1000") // wait max 1s
23 | objset.Set("web.enableJavascript", "false")
24 | objset.Set("web.enablePlugins", "false")
25 | objset.Set("web.loadImages", "true")
26 | objset.Set("web.background", "true")
27 |
28 | c := gs.NewConverter()
29 | c.Add(objset)
30 | //c.AddHtml(os, "
HELLO
World
")
31 |
32 | c.ProgressChanged = func(c *wkhtmltopdf.Converter, b int) {
33 | fmt.Printf("Progress: %d\n", b)
34 | }
35 | c.Error = func(c *wkhtmltopdf.Converter, msg string) {
36 | fmt.Printf("error: %s\n", msg)
37 | }
38 | c.Warning = func(c *wkhtmltopdf.Converter, msg string) {
39 | fmt.Printf("error: %s\n", msg)
40 | }
41 | c.Phase = func(c *wkhtmltopdf.Converter) {
42 | fmt.Printf("Phase\n")
43 | }
44 | c.Finished = func(c *wkhtmltopdf.Converter, s int) {
45 | fmt.Printf("Finished: %d\n", s)
46 | }
47 | c.Convert()
48 |
49 | payload, _ := c.Payload()
50 |
51 | ioutil.WriteFile("test.pdf", payload, 0644)
52 |
53 | fmt.Printf("Got error code: %d\n", c.ErrorCode())
54 | }
55 |
--------------------------------------------------------------------------------
/wkhtmltopdf/pdf_c_api.go:
--------------------------------------------------------------------------------
1 | package wkhtmltopdf
2 |
3 | //#cgo CFLAGS: -I/usr/local/include
4 | //#cgo LDFLAGS: -L/usr/local/lib -lwkhtmltox -Wall -ansi -pedantic -ggdb
5 | //#include
6 | //#include
7 | //#include
8 | //#include
9 | //#include
10 | //extern void finished_cb(void*, const int);
11 | //extern void progress_changed_cb(void*, const int);
12 | //extern void error_cb(void*, char *msg);
13 | //extern void warning_cb(void*, char *msg);
14 | //extern void phase_changed_cb(void*);
15 | //static void setup_callbacks(wkhtmltopdf_converter * c) {
16 | // wkhtmltopdf_set_finished_callback(c, (wkhtmltopdf_int_callback)finished_cb);
17 | // wkhtmltopdf_set_progress_changed_callback(c, (wkhtmltopdf_int_callback)progress_changed_cb);
18 | // wkhtmltopdf_set_error_callback(c, (wkhtmltopdf_str_callback)error_cb);
19 | // wkhtmltopdf_set_warning_callback(c, (wkhtmltopdf_str_callback)warning_cb);
20 | // wkhtmltopdf_set_phase_changed_callback(c, (wkhtmltopdf_void_callback)phase_changed_cb);
21 | //}
22 | import "C"
23 |
24 | import (
25 | "fmt"
26 | "unsafe"
27 | "reflect"
28 | )
29 |
30 | type GlobalSettings struct {
31 | s *C.wkhtmltopdf_global_settings
32 | }
33 |
34 | type ObjectSettings struct {
35 | s *C.wkhtmltopdf_object_settings
36 | }
37 |
38 | type Converter struct {
39 | c *C.wkhtmltopdf_converter
40 | Finished func(*Converter, int)
41 | ProgressChanged func(*Converter, int)
42 | Error func(*Converter, string)
43 | Warning func(*Converter, string)
44 | Phase func(*Converter)
45 | }
46 |
47 | var converter_map map[unsafe.Pointer]*Converter
48 |
49 | func init() {
50 | converter_map = map[unsafe.Pointer]*Converter{}
51 | C.wkhtmltopdf_init(C.false)
52 | }
53 |
54 | func NewGlobalSettings() *GlobalSettings {
55 | return &GlobalSettings{s: C.wkhtmltopdf_create_global_settings()}
56 | }
57 |
58 | // See https://wkhtmltopdf.org/libwkhtmltox/pagesettings.html#pagePdfGlobal for more setttings
59 | func (self *GlobalSettings) Set(name, value string) {
60 | c_name := C.CString(name)
61 | c_value := C.CString(value)
62 | defer C.free(unsafe.Pointer(c_name))
63 | defer C.free(unsafe.Pointer(c_value))
64 | C.wkhtmltopdf_set_global_setting(self.s, c_name, c_value)
65 | }
66 |
67 | func NewObjectSettings() *ObjectSettings {
68 | return &ObjectSettings{s: C.wkhtmltopdf_create_object_settings()}
69 | }
70 |
71 | func (self *ObjectSettings) Set(name, value string) {
72 | c_name := C.CString(name)
73 | c_value := C.CString(value)
74 | defer C.free(unsafe.Pointer(c_name))
75 | defer C.free(unsafe.Pointer(c_value))
76 | C.wkhtmltopdf_set_object_setting(self.s, c_name, c_value)
77 | }
78 |
79 | func (self *GlobalSettings) NewConverter() *Converter {
80 | c := &Converter{c: C.wkhtmltopdf_create_converter(self.s)}
81 | C.setup_callbacks(c.c)
82 |
83 | return c
84 | }
85 |
86 | //export finished_cb
87 | func finished_cb(c unsafe.Pointer, s C.int) {
88 | conv := converter_map[c]
89 | if conv.Finished != nil {
90 | conv.Finished(conv, int(s))
91 | }
92 | }
93 |
94 | //export progress_changed_cb
95 | func progress_changed_cb(c unsafe.Pointer, p C.int) {
96 | conv := converter_map[c]
97 | if conv.ProgressChanged != nil {
98 | conv.ProgressChanged(conv, int(p))
99 | }
100 | }
101 |
102 | //export error_cb
103 | func error_cb(c unsafe.Pointer, msg *C.char) {
104 | conv := converter_map[c]
105 | if conv.Error != nil {
106 | conv.Error(conv, C.GoString(msg))
107 | }
108 | }
109 |
110 | //export warning_cb
111 | func warning_cb(c unsafe.Pointer, msg *C.char) {
112 | conv := converter_map[c]
113 | if conv.Warning != nil {
114 | conv.Warning(conv, C.GoString(msg))
115 | }
116 | }
117 |
118 | //export phase_changed_cb
119 | func phase_changed_cb(c unsafe.Pointer) {
120 | conv := converter_map[c]
121 | if conv.Phase != nil {
122 | conv.Phase(conv)
123 | }
124 | }
125 |
126 | func (self *Converter) Convert() error {
127 |
128 | // To route callbacks right, we need to save a reference
129 | // to the converter object, base on the pointer.
130 | converter_map[unsafe.Pointer(self.c)] = self
131 | status := C.wkhtmltopdf_convert(self.c)
132 | delete(converter_map, unsafe.Pointer(self.c))
133 | if status != C.int(1) {
134 | return fmt.Errorf("Convert failed (%d)", status)
135 | }
136 | return nil
137 | }
138 |
139 | func (self *Converter) Add(settings *ObjectSettings) {
140 | C.wkhtmltopdf_add_object(self.c, settings.s, nil)
141 | }
142 |
143 | func (self *Converter) AddHtml(settings *ObjectSettings, data string) {
144 | c_data := C.CString(data)
145 | defer C.free(unsafe.Pointer(c_data))
146 | C.wkhtmltopdf_add_object(self.c, settings.s, c_data)
147 | }
148 |
149 | func (self *Converter) ErrorCode() int {
150 | return int(C.wkhtmltopdf_http_error_code(self.c))
151 | }
152 |
153 | func (self *Converter) Destroy() {
154 | C.wkhtmltopdf_destroy_converter(self.c)
155 | }
156 |
157 | func (self *Converter) Payload() ([]byte, int) {
158 | var payloadptr *C.uchar
159 | length := int(C.wkhtmltopdf_get_output(self.c, &payloadptr))
160 | var payload []byte
161 | header := (*reflect.SliceHeader)(unsafe.Pointer(&payload))
162 |
163 | header.Len = length
164 |
165 | header.Cap = length
166 |
167 | header.Data = uintptr(unsafe.Pointer(payloadptr))
168 | return payload, length
169 | }
170 |
--------------------------------------------------------------------------------