2016-04-07 7 views
2

Ich versuche, eine Beispielbibliothek für gemeinsam genutzte Objekte mit Go zu erstellen. Der Code kompiliert (mit dem Befehl go build -o libsample.so -buildmode=c-shared .), eine Shared Object-Bibliothek wird erfolgreich erstellt - aber beim Zugriff auf die exportierte Methode über JNA (von Java) oder Ctypes (von Python), bekomme ich eine Panik. Der Code, den ich in Go geschrieben ist:nicht genügend Speicher beim Zugriff auf eine Funktion von einer gemeinsam genutzten Bibliothek

// package name: libsample.so 
package main 

import "C" 
import "fmt" 

//export Hello 
func Hello(s string) { 
    fmt.Println("Hello " + s + "!") 
} 

func main() { 
} 

Während diese Methode Hello von Java zugreifen:

import com.sun.jna.*; 

public class sample { 

    public interface GoSO extends Library { 
     GoSO INSTANCE = (GoSO) Native.loadLibrary("sample" ,GoSO.class); 
     void Hello(String s); 
    } 
    public static void main(String[] args) { 
     GoSO.INSTANCE.Hello("World"); 
    } 
} 

oder von Python:

#!/usr/bin/python 
import ctypes 
lib = ctypes.CDLL("./libsample.so") 
lib.Hello("World") 

bekomme ich folgende Fehlermeldung:

runtime: out of memory: cannot allocate 140042998120448-byte block (1048576 in use) 
fatal error: out of memory 

runtime stack: 
runtime.throw(0x7f5e434bfe50, 0xd) 
    /usr/local/go/src/runtime/panic.go:530 +0x92 
runtime.largeAlloc(0x7f5e4d27dc8d, 0xc800000003, 0xc82003cf08) 
    /usr/local/go/src/runtime/malloc.go:768 +0xdf 
runtime.mallocgc.func3() 
    /usr/local/go/src/runtime/malloc.go:664 +0x35 
runtime.systemstack(0x7f5e4e4d3ab8) 
    /usr/local/go/src/runtime/asm_amd64.s:291 +0x72 
runtime.mstart() 
    /usr/local/go/src/runtime/proc.go:1048 

goroutine 17 [running, locked to thread]: 
runtime.systemstack_switch() 
    /usr/local/go/src/runtime/asm_amd64.s:245 fp=0xc82003cb50 sp=0xc82003cb48 
runtime.mallocgc(0x7f5e4d27dc8d, 0x0, 0x3, 0x0) 
    /usr/local/go/src/runtime/malloc.go:665 +0x9fe fp=0xc82003cc28 sp=0xc82003cb50 
runtime.rawstring(0x7f5e4d27dc8d, 0x0, 0x0, 0x0, 0x0, 0x0) 
    /usr/local/go/src/runtime/string.go:284 +0x72 fp=0xc82003cc70 sp=0xc82003cc28 
runtime.rawstringtmp(0x0, 0x7f5e4d27dc8d, 0x0, 0x0, 0x0, 0x0, 0x0) 
    /usr/local/go/src/runtime/string.go:111 +0xb9 fp=0xc82003cca8 sp=0xc82003cc70 
runtime.concatstrings(0x0, 0xc82003ce38, 0x3, 0x3, 0x0, 0x0) 
    /usr/local/go/src/runtime/string.go:49 +0x1bf fp=0xc82003cde0 sp=0xc82003cca8 
runtime.concatstring3(0x0, 0x7f5e434ba9d0, 0x6, 0x7f5e48155490, 0x7f5e4d27dc86, 0x7f5e434ba560, 0x1, 0x0, 0x0) 
    /usr/local/go/src/runtime/string.go:63 +0x6c fp=0xc82003ce30 sp=0xc82003cde0 
main.Hello(0x7f5e48155490, 0x7f5e4d27dc86) 
    /home/vagrant/go/src/github.com/venkatramachandran/lib-sample/sample.go:9 +0x72 fp=0xc82003cec8 sp=0xc82003ce30 
main._cgoexpwrap_9f7405a93e67_Hello(0x7f5e48155490, 0x7f5e4d27dc86) 
    github.com/venkatramachandran/lib-sample/_obj/_cgo_gotypes.go:48 +0x2d fp=0xc82003cee0 sp=0xc82003cec8 
runtime.call32(0x0, 0x7f5e4e4d3ae8, 0x7f5e4e4d3b70, 0x10) 
    /usr/local/go/src/runtime/asm_amd64.s:472 +0x40 fp=0xc82003cf08 sp=0xc82003cee0 
runtime.cgocallbackg1() 
    /usr/local/go/src/runtime/cgocall.go:267 +0x110 fp=0xc82003cf40 sp=0xc82003cf08 
runtime.cgocallbackg() 
    /usr/local/go/src/runtime/cgocall.go:180 +0xd9 fp=0xc82003cfa0 sp=0xc82003cf40 
runtime.cgocallback_gofunc(0x0, 0x0, 0x0) 
    /usr/local/go/src/runtime/asm_amd64.s:716 +0x5d fp=0xc82003cfb0 sp=0xc82003cfa0 
runtime.goexit() 
    /usr/local/go/src/runtime/asm_amd64.s:1998 +0x1 fp=0xc82003cfb8 sp=0xc82003cfb0 

goroutine 18 [syscall, locked to thread]: 
runtime.goexit() 
    /usr/local/go/src/runtime/asm_amd64.s:1998 +0x1 
Aborted (core dumped) 

Was läuft falsch? Wenn ich eine Methode mit einem int oder einem float als Parameter erstelle, tritt dieser Fehler nicht auf.

Antwort

4

Grund: Der Grund dafür ist, dass Ihre Go-Funktion Hello erwartet einen golang String, aber Python und Java übergeben C style String.

Lösung: Da Sie Ihre Golang-Bibliothek mit buildmode=c-shared kompiliert haben. Python ctypes Paket und Java JNI sieht es als eine einfache c-Methode. Und übergibt eine c-Stil-Zeichenfolge, die wirklich nur ein Array von Zeichen ist, die durch NULL abgeschlossen sind.

Aber in Ihrem Code, Funktion Hello erwartet eine Golang-Zeichenfolge, die ein anderes Format als typische c-Stil-Zeichenfolge hat. Daher dieser Fehler.

Es kann gelöst werden, indem s als *C.char deklariert wird.

Korrigierte Programm ist wie folgt:

// package name: libsample.so 
package main 

import "C" 
import "fmt" 

//export Hello 
func Hello(s *C.char) { 
    fmt.Println("Hello " + C.GoString(s) + "!") 
} 

func main() { 
} 
Verwandte Themen