Hacker News new | ask | show | jobs
by timtadh 4685 days ago
How it works (from http://golang.org/src/pkg/runtime/cgocall.c )

    36	// The above description skipped over the possibility of the gcc-compiled
    37	// function f calling back into Go.  If that happens, we continue down
    38	// the rabbit hole during the execution of f.
    39	//
    40	// To make it possible for gcc-compiled C code to call a Go function p.GoF,
    41	// cgo writes a gcc-compiled function named GoF (not p.GoF, since gcc doesn't
    42	// know about packages).  The gcc-compiled C function f calls GoF.
    43	//
    44	// GoF calls crosscall2(_cgoexp_GoF, frame, framesize).  Crosscall2
    45	// (in cgo/gcc_$GOARCH.S, a gcc-compiled assembly file) is a two-argument
    46	// adapter from the gcc function call ABI to the 6c function call ABI.
    47	// It is called from gcc to call 6c functions.  In this case it calls
    48	// _cgoexp_GoF(frame, framesize), still running on m->g0's stack
    49	// and outside the $GOMAXPROCS limit.  Thus, this code cannot yet
    50	// call arbitrary Go code directly and must be careful not to allocate
    51	// memory or use up m->g0's stack.
    52	//
    53	// _cgoexp_GoF calls runtime.cgocallback(p.GoF, frame, framesize).
    54	// (The reason for having _cgoexp_GoF instead of writing a crosscall3
    55	// to make this call directly is that _cgoexp_GoF, because it is compiled
    56	// with 6c instead of gcc, can refer to dotted names like
    57	// runtime.cgocallback and p.GoF.)
    58	//
    59	// runtime.cgocallback (in asm_$GOARCH.s) switches from m->g0's
    60	// stack to the original g (m->curg)'s stack, on which it calls
    61	// runtime.cgocallbackg(p.GoF, frame, framesize).
    62	// As part of the stack switch, runtime.cgocallback saves the current
    63	// SP as m->g0->sched.sp, so that any use of m->g0's stack during the
    64	// execution of the callback will be done below the existing stack frames.
    65	// Before overwriting m->g0->sched.sp, it pushes the old value on the
    66	// m->g0 stack, so that it can be restored later.
    67	//
    68	// runtime.cgocallbackg (below) is now running on a real goroutine
    69	// stack (not an m->g0 stack).  First it calls runtime.exitsyscall, which will
    70	// block until the $GOMAXPROCS limit allows running this goroutine.
    71	// Once exitsyscall has returned, it is safe to do things like call the memory
    72	// allocator or invoke the Go callback function p.GoF.  runtime.cgocallbackg
    73	// first defers a function to unwind m->g0.sched.sp, so that if p.GoF
    74	// panics, m->g0.sched.sp will be restored to its old value: the m->g0 stack
    75	// and the m->curg stack will be unwound in lock step.
    76	// Then it calls p.GoF.  Finally it pops but does not execute the deferred
    77	// function, calls runtime.entersyscall, and returns to runtime.cgocallback.
    78	//
    79	// After it regains control, runtime.cgocallback switches back to
    80	// m->g0's stack (the pointer is still in m->g0.sched.sp), restores the old
    81	// m->g0.sched.sp value from the stack, and returns to _cgoexp_GoF.
    82	//
    83	// _cgoexp_GoF immediately returns to crosscall2, which restores the
    84	// callee-save registers for gcc and returns to GoF, which returns to f.
1 comments

I'm not particularly familiar with either language... that documentation seems to be talking only about Go called from C-called-from-Go, not from arbitrary C. In other words, it handles Go calling a C function that expects a callback, and handing it a Go function. This does not handle a fundamentally-C program calling a Go function.

Again, not an expert, I could be mistaken, but this seems to not be addressing the original issue raised (that C/Go interop is one-way only).