Use another language to call a function: Difference between revisions

Content added Content deleted
(Undo revision 212588 by SamLex (talk))
(Added alternative Go solution (after summary message mess up))
Line 278: Line 278:
Output:
Output:
<pre>
<pre>
Here am I
</pre>

=== Alternative Method ===
As of Go 1.5, this is now possible without modifying the C code thanks to the addition of buildmodes. Buildmodes allow Go code to be compiled to standard C libraries (both dynamic and static).

The Go code for this task is as follows:
<lang go>
// This buildmode requires the package to be main
package main

// Import C so we can export the function to C and use C types

//#include <stdlib.h> // for size_t
import "C"

// Import reflect and unsafe so we can wrap the C array in a Go slice
import "reflect"
import "unsafe"

// This buildmode also requires a main function, but it is never actually called
func main() {}

// The message to copy into the buffer
const msg = "Here am I"

// Here we declare the Query function using C types and export it to C

//export Query
func Query(buffer *C.char, length *C.size_t) C.int {
// Check there is enough space in the buffer
if int(*length) < len(msg) {
return 0
}

// Wrap the buffer in a slice to make it easier to copy into
sliceHeader := reflect.SliceHeader {
Data: uintptr(unsafe.Pointer(buffer)),
Len: len(msg),
Cap: len(msg),
}
bufferSlice := *(*[]byte)(unsafe.Pointer(&sliceHeader))

// Iterate through the message and copy it to the buffer, byte by byte
for i:=0;i<len(msg);i++ {
bufferSlice[i] = msg[i]
}

// Set length to the amount of bytes we copied
(*length) = C.size_t(len(msg))

return 1
}
</lang>

Assuming this is saved to query.go (and that the C code is saved as main.c) it can be compiled with:
<pre>
$ go build -buildmode=c-shared query.go
$ gcc main.c -L. -lquery -o main
</pre>

This creates a library file, a header file for the library (not used) and an executable dynamically linked to the library file.

The executable can be run with:
<pre>
$ LD_LIBRARY_PATH=. ./main
Here am I
Here am I
</pre>
</pre>