|
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.
|
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).