Skip to content

Commit 63a4522

Browse files
authored
Support different output streams than os.Stderr for std.trace (C API) (google#520)
Support different output streams than os.Stderr for std.trace (C API)
1 parent 7d81091 commit 63a4522

File tree

4 files changed

+73
-2
lines changed

4 files changed

+73
-2
lines changed

c-bindings-tests/compat_test.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
#!/usr/bin/env python3
2-
import unittest
32
import ctypes
4-
import re
3+
import io
54
import os
5+
import re
6+
import unittest
67

78

89
lib = ctypes.CDLL('../c-bindings/libgojsonnet.so')
@@ -128,6 +129,19 @@
128129
]
129130
lib.jsonnet_import_callback.restype = None
130131

132+
IO_WRITER_CALLBACK = ctypes.CFUNCTYPE(
133+
ctypes.c_int,
134+
ctypes.c_void_p,
135+
ctypes.c_size_t,
136+
ctypes.POINTER(ctypes.c_int)
137+
)
138+
139+
lib.jsonnet_set_trace_out_callback.argtypes = [
140+
ctypes.c_void_p,
141+
IO_WRITER_CALLBACK,
142+
]
143+
lib.jsonnet_set_trace_out_callback.restype = None
144+
131145
# json declaration
132146

133147
lib.jsonnet_json_make_string.argtypes = [
@@ -339,6 +353,15 @@ def import_callback(ctx, dir, rel, found_here, success):
339353

340354
return ctypes.addressof(dst.contents)
341355

356+
io_writer_buf = None
357+
358+
@IO_WRITER_CALLBACK
359+
def io_writer_callback(buf, nbytes, success):
360+
global io_writer_buf
361+
io_writer_buf = ctypes.string_at(buf, nbytes)
362+
success[0] = ctypes.c_int(1)
363+
return nbytes
364+
342365
# Returns content if worked, None if file not found, or throws an exception
343366
def jsonnet_try_path(dir, rel):
344367
if not rel:
@@ -490,6 +513,15 @@ def test_jsonnet_import_callback(self):
490513
self.assertEqual(b'42\n', to_bytes(res))
491514
free_buffer(self.vm, res)
492515

516+
def test_jsonnet_set_trace_out_callback(self):
517+
lib.jsonnet_set_trace_out_callback(self.vm, io_writer_callback)
518+
fname = b"vm1"
519+
msg = b"test_jsonnet_set_trace_out_callback trace message"
520+
expected = b"TRACE: " + fname + b":1 " + msg + b"\n"
521+
snippet = b"std.trace('" + msg + b"', 'rest')"
522+
lib.jsonnet_evaluate_snippet(self.vm, fname, snippet, self.err_ref)
523+
self.assertEqual(io_writer_buf, expected)
524+
493525
def tearDown(self):
494526
lib.jsonnet_destroy(self.vm)
495527

c-bindings/c-bindings.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,5 +639,29 @@ func formatSnippet(vmRef *C.struct_JsonnetVm, filename string, code string, e *C
639639
return result
640640
}
641641

642+
type traceOut struct {
643+
cb *C.JsonnetIoWriterCallback
644+
}
645+
646+
func (o *traceOut) Write(p []byte) (int, error) {
647+
if len(p) == 0 {
648+
return 0, nil
649+
}
650+
651+
success := C.int(0)
652+
var n C.int = C.jsonnet_internal_execute_writer(o.cb, unsafe.Pointer(&p[0]),
653+
C.size_t(len(p)), &success)
654+
if success != 1 {
655+
return int(n), errors.New("std.trace() failed to write to output stream")
656+
}
657+
return int(n), nil
658+
}
659+
660+
//export jsonnet_set_trace_out_callback
661+
func jsonnet_set_trace_out_callback(vmRef *C.struct_JsonnetVm, cb *C.JsonnetIoWriterCallback) {
662+
vm := getVM(vmRef)
663+
vm.SetTraceOut(&traceOut{cb})
664+
}
665+
642666
func main() {
643667
}

c-bindings/internal.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,11 @@ char* jsonnet_internal_execute_import(JsonnetImportCallback *cb,
3838
char **found_here,
3939
int *success);
4040

41+
typedef int JsonnetIoWriterCallback(const void *buf, size_t nbytes, int *success);
42+
43+
int jsonnet_internal_execute_writer(JsonnetIoWriterCallback *cb,
44+
const void *buf,
45+
size_t nbytes,
46+
int *success);
47+
4148
void jsonnet_internal_free_string(char *str);

c-bindings/libjsonnet.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ char* jsonnet_internal_execute_import(JsonnetImportCallback *cb,
4444
return (cb)(ctx, base, rel, found_here, success);
4545
}
4646

47+
int jsonnet_internal_execute_writer(JsonnetIoWriterCallback *cb,
48+
const void *buf,
49+
size_t nbytes,
50+
int *success)
51+
{
52+
return (cb)(buf, nbytes, success);
53+
}
54+
4755
void jsonnet_internal_free_string(char *str) {
4856
if (str != nullptr) {
4957
::free(str);

0 commit comments

Comments
 (0)