From dc74089a97453ccb1a1a74078170bd50258a04b1 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sat, 16 Apr 2016 15:24:14 +0200 Subject: Fix CGo callback See: https://github.com/kch42/golibrsync/issues/1 It is not allowed to let C directly call Go functions, wrapper functions must be made. For some reason, it appears to have worked before but it doesn't work now. --- librsync/librsync.go | 33 ++++++++++++--------------------- librsync/librsync_callback.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 21 deletions(-) create mode 100644 librsync/librsync_callback.go diff --git a/librsync/librsync.go b/librsync/librsync.go index 57c9cfb..bf60a1d 100644 --- a/librsync/librsync.go +++ b/librsync/librsync.go @@ -7,9 +7,14 @@ package librsync #include #include -rs_buffers_t* new_rs_buffers() { +static inline rs_buffers_t* new_rs_buffers() { return (rs_buffers_t*) malloc(sizeof(rs_buffers_t)); } + +rs_result patchCallback(void* _patcher, rs_long_t pos, size_t* len, void** _buf) { + return patchCallbackGo(_patcher, pos, len, _buf); +} + */ import "C" @@ -118,6 +123,10 @@ func (jp jobInternalPanic) Error() string { return jp.err.Error() } func jobIter(job *C.rs_job_t, rsbufs *C.rs_buffers_t) (running bool, err error) { defer func() { r := recover() + if r == nil { + // there was no panic + return + } jp, ok := r.(jobInternalPanic) if !ok { panic(r) @@ -271,25 +280,7 @@ type Patcher struct { buf []byte } -func _patch_callback(_patcher unsafe.Pointer, pos C.rs_long_t, len *C.size_t, _buf *unsafe.Pointer) C.rs_result { - patcher := (*Patcher)(_patcher) - - patcher.buf = make([]byte, int(*len)) - n, err := patcher.basis.ReadAt(patcher.buf, int64(pos)) - if n < int(*len) { - if err != io.EOF { - panic(jobInternalPanic{err}) - } else { - return C.RS_INPUT_ENDED - } - } - *len = C.size_t(n) - *_buf = unsafe.Pointer(&(patcher.buf[0])) - - return C.RS_DONE -} - -var patch_callback = _patch_callback // So we can use the `&` operator in NewPatcher +var patchCallback = C.patchCallback // So we can use the `&` operator in NewPatcher // NewPatcher creates a Patcher (which basically is a Job object with some hidden extra data). // @@ -306,7 +297,7 @@ func NewPatcher(delta io.Reader, basis io.ReaderAt) (job *Patcher, err error) { Job: _job, basis: basis} - job.job = C.rs_patch_begin((*C.rs_copy_cb)(unsafe.Pointer(&patch_callback)), unsafe.Pointer(job)) + job.job = C.rs_patch_begin((*C.rs_copy_cb)(patchCallback), unsafe.Pointer(job)) if job.job == nil { job.Close() return nil, errors.New("rs_patch_begin failed") diff --git a/librsync/librsync_callback.go b/librsync/librsync_callback.go new file mode 100644 index 0000000..c8b9e4f --- /dev/null +++ b/librsync/librsync_callback.go @@ -0,0 +1,31 @@ +package librsync + +/* +#include +#include +*/ +import "C" + +import ( + "io" + "unsafe" +) + +//export patchCallbackGo +func patchCallbackGo(_patcher unsafe.Pointer, pos C.rs_long_t, len *C.size_t, _buf *unsafe.Pointer) C.rs_result { + patcher := (*Patcher)(_patcher) + + patcher.buf = make([]byte, int(*len)) + n, err := patcher.basis.ReadAt(patcher.buf, int64(pos)) + if n < int(*len) { + if err != io.EOF { + panic(jobInternalPanic{err}) + } else { + return C.RS_INPUT_ENDED + } + } + *len = C.size_t(n) + *_buf = unsafe.Pointer(&(patcher.buf[0])) + + return C.RS_DONE +} -- cgit v1.2.3-54-g00ecf From 3275f0686a08d8e323568036f003b92b6655808c Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sat, 16 Apr 2016 15:28:14 +0200 Subject: go fmt --- librsync/librsync.go | 8 ++++---- librsync/librsync_test.go | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/librsync/librsync.go b/librsync/librsync.go index bf60a1d..a3a4e87 100644 --- a/librsync/librsync.go +++ b/librsync/librsync.go @@ -79,7 +79,7 @@ func NewDefaultSignatureGen(basis io.Reader) (job *Job, err error) { } // NewSignatureGen creates a signature generation job. -// +// // blocklen is the length of a block. // stronglen is the length of the stong hash. // basis is an io.Reader that provides data of the basis file. @@ -253,7 +253,7 @@ func LoadSignature(input io.Reader) (sig Signature, err error) { } // NewDeltaGen creates a delta generation job. -// +// // sig is the signature loaded by LoadSignature. // newfile is a reades that provides the new, modified data. func NewDeltaGen(sig Signature, newfile io.Reader) (job *Job, err error) { @@ -272,7 +272,7 @@ func NewDeltaGen(sig Signature, newfile io.Reader) (job *Job, err error) { } // Patcher is a job with additional hidden data for patching. -// +// // IMPORTANT: You still need to Close() this! type Patcher struct { *Job @@ -283,7 +283,7 @@ type Patcher struct { var patchCallback = C.patchCallback // So we can use the `&` operator in NewPatcher // NewPatcher creates a Patcher (which basically is a Job object with some hidden extra data). -// +// // delta is a reader that provides the delta. // basis provides the basis file. func NewPatcher(delta io.Reader, basis io.ReaderAt) (job *Patcher, err error) { diff --git a/librsync/librsync_test.go b/librsync/librsync_test.go index 256e344..7c6a278 100644 --- a/librsync/librsync_test.go +++ b/librsync/librsync_test.go @@ -59,7 +59,7 @@ func TestSignatureDeltaPatch(t *testing.T) { } } - // Apply Patch + // Apply Patch patchres := new(bytes.Buffer) patcher, err := NewPatcher(deltabuf, orig) if err != nil { -- cgit v1.2.3-54-g00ecf