On Wed, Apr 5, 2017 at 12:22 AM, distributed <distribu...@gloenggi.ch> wrote: > I am currently wrapping a proprietary library with cgo. > > About error reporting, the library documentation says "Every function that > can fail returns at least boolean or pointer value that can be used to > detect error state (false and NULL means error, every other value means > success). If such error happens, details about it can be queried using > thelib_error(). The error information is thread-local." > > So when calling a function from the library, in C I write about the > following code: > > bool ret = thelib_dosomework(...); > if (!ret) { > // call has to be in same thread as call to thelib_dosomework() above > int errcode = thelib_error(buf, BUF_SIZ, null); > fprintf(stderr, "error %d: %s\n", errcode, buf); > return false; > } > > > My current approach to call a C function from the library and get the > corresponding error information looks like this: > > func callIntoTheLib() error { > runtime.LockOSThread() > defer runtime.UnlockOSThread() > > ret := C.thelib_dosomework(...) > if !ret { > return extractErrorFromTheLibError() > } > > return nil > } > > func extractErrorFromTheLibError() error { > var buf [1024]byte > var outsize C.size_t > errcode := C.thelib_error((*C.char)(unsafe.Pointer((&errbuf[0]))), > C.size_t(len(errbuf)), &outsize) > // not wrapping in struct type for brevity > return fmt.Errorf("error %d: %s", errcode, buf[:outsize]) > } > > > > Is this sensible? Looking at the runtime implementation, > LockOSThread/UnlockOSThread seem to be really simple as the only save a > couple of words in goroutine storage. I don't mind about using up an OS > thread as there will not be a large number of concurrent calls into the > library. Also, calls into C use up one thread anyway and the majority of > time will be spent in the payload call, not in thelib_error(), which is a > short and fast function.
Yes, that seems fine. Every cgo call calls LockOSThread internally anyhow, so you are just extending that lock across, potentially, two calls. > Another approach I was thinking about was to copy the error message and code > to memory in C code, but with this approach I always have to have a > preallocated buffer for an error that might not happen. Not really. On error you could malloc a buffer, copy in the string, and return the buffer to Go. In Go you could copy the buffer into Go memory and C.free the buffer. That approach isn't any better than what you are doing today, but it would work (it does copy the buffer twice, but presumably errors are not the common case). Ian -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.