Verwendung von Go-Code in einem bestehenden C-Projekt

Lesezeit: 4 Minuten

Benutzeravatar von dreadiscool
fürchterlich

Seit Go 1.5 herauskam, habe ich angefangen, mich erneut damit zu beschäftigen, wie ich es in ein bestehendes Projekt von mir integrieren könnte.

Die Codebasis des Projekts ist vollständig in C geschrieben, um einen Low-Level-Zugriff auf Hardware und andere lustige Dinge zu ermöglichen. Einige der Dinge auf höherer Ebene sind jedoch langweilig, und ich würde gerne anfangen, sie in einer Sprache auf höherer Ebene zu schreiben (Go).

Gibt es eine Möglichkeit, Go-Code von einem C-Programm aus aufzurufen? Ich habe Go 1.5 installiert, was hinzugefügt wurde -buildmode=c-archive (https://golang.org/s/execmodes), die ich versuche zum Laufen zu bringen.

Ich kann Go jedoch anscheinend nicht dazu bringen, die entsprechenden Header-Dateien zu generieren, damit mein Projekt tatsächlich kompiliert werden kann. Wenn ich das Archiv generiere, sehe ich die Funktion in den exportierten Symbolen (mit objdump), aber ohne die Header-Dateien zum Einbinden von gcc beschwert sich, dass die Funktion nicht vorhanden ist (wie erwartet).

Ich bin ziemlich neu in Go, aber ich liebe die Sprache und würde sie gerne nutzen. Gibt es einen idiomatischen Weg (“idiomatisch” wird in der Welt von Go, wie ich sehe, oft verwendet …), um dies dazu zu bringen, gut miteinander zu spielen?

Der Grund, warum ich diese Frage gestellt und Go 1.5 ausdrücklich erwähnt habe, ist, dass laut diesem Dokument https://docs.google.com/document/d/1nr-TQHw_er6GOQRsF6T43GGhFDelrAP0NqSS_00RgZQ/edit?pli=1#heading=h.1gw5ytjfcoke
Go 1.5 fügte Unterstützung für Nicht-Go-Programme hinzu, um Go-Code aufzurufen. Insbesondere erwähnt im Abschnitt „Go-Code, der mit einem Nicht-Go-Programm verknüpft ist und von einem Nicht-Go-Programm aufgerufen wird“

  • Exportierst du über cgo? Das Dokument, auf das Sie verlinken, sagt: „Die einzigen aufrufbaren Symbole sind diejenigen, die als exportiert markiert sind (von jedem Paket), wie in beschrieben cgo-Dokumentation.” Dieser Link zur cgo-Dokumentation erwähnt eine generierte _cgo_export.h.

    – David C

    25. August 2015 um 23:53 Uhr

  • Eine frühere Frage sagte, die Antwort sei nein. Ich wäre neugierig, ob sich in 1.5 etwas geändert hat, aber ich bezweifle es: stackoverflow.com/questions/6125683/call-go-functions-from-c

    – Gabriel Süd

    25. August 2015 um 23:55 Uhr


  • Der Grund, warum ich Go 1.5 erwähnt habe, war, dass dieses Dokument ausdrücklich die Möglichkeit erwähnt, gemeinsam genutzte Objektdateien oder Archivdateien zu erstellen, die von Systemen aufgerufen werden können, die keinen Go-Code erwarten , ein Nicht-Go-Programm” in diesem Link docs.google.com/document/d/…

    – fürchterlich

    26. August 2015 um 1:07 Uhr

  • Dave C ist auf der Spur–blog.filippo.io/building-python-modules-with-go-1-5 hat mehr (im Zusammenhang mit der Verbindung von Go mit Python über c-shared archivieren u cgo Exporte), aber ich habe jetzt nicht die Zeit, das zu einer zusammenhängenden Antwort zusammenzufügen. Es scheint jedoch, dass Sie Go jetzt von C aus verwenden können.

    – zweizweizwei

    26. August 2015 um 1:47 Uhr


  • Ich habe cgo erwähnt nicht als Möglichkeit, mit C-Code zu interagieren, aber so, wie Sie es brauchen Kennzeichen welche Funktionen exportiert und von C aufgerufen werden sollen (im Grunde nur eine //export … Kommentar). Wie in meinem Kommentar erwähnt, wird dies in dem genau verlinkten Dokument beschrieben.

    – David C

    26. August 2015 um 17:21 Uhr


Benutzeravatar von James Henstridge
James Henstridge

Um ein von C aufrufbares Archiv zu erstellen, müssen Sie sie als exportierte CGo-Symbole markieren.
Zum Beispiel, wenn ich eine Datei erstelle foo.go mit folgendem Inhalt:

package main

import (
    "C"
    "fmt"
)

//export PrintInt
func PrintInt(x int) {
    fmt.Println(x)
}

func main() {}

Die wichtigen Dinge zu beachten sind:

  • Das Paket muss aufgerufen werden main
  • Sie müssen eine haben main Funktion, obwohl sie leer sein kann.
  • Sie müssen das Paket importieren C
  • Sie brauchen etwas Besonderes //export Kommentare, um die Funktionen zu markieren, die von C aufgerufen werden sollen.

Ich kann es mit dem folgenden Befehl als aufrufbare statische C-Bibliothek kompilieren:

go build -buildmode=c-archive foo.go

Die Ergebnisse werden ein Archiv sein foo.a und eine Überschrift foo.h. In der Kopfzeile erhalten wir Folgendes (ohne irrelevante Teile):

...
typedef long long GoInt64;
...
typedef GoInt64 GoInt;
...
extern void PrintInt(GoInt p0);
...

Das reicht also aus, um die exportierte Funktion aufzurufen. Wir können ein einfaches C-Programm schreiben, das es so aufruft:

#include "foo.h"

int main(int argc, char **argv) {
    PrintInt(42);
    return 0;
}

Wir können es mit einem Befehl wie dem folgenden kompilieren:

gcc -pthread foo.c foo.a -o foo

Das -pthread Option ist erforderlich, da die Go-Laufzeit Threads verwendet. Wenn ich die resultierende ausführbare Datei ausführe, wird sie gedruckt 42.

  • Verschiedene Frage: Gibt es eine Möglichkeit, dies beim Cross-Compilieren für Windows von OSX zum Laufen zu bringen? Dieser Teil wird fehlschlagen: GOOS=windows GOARCH=amd64 go build -buildmode=c-archive foo.go

    – mwag

    16. Oktober 2016 um 4:05 Uhr

  • IIRC, CGo wird beim Cross-Building standardmäßig deaktiviert. Sie können es mit wieder aktivieren CGO_ENABLED=1aber Sie müssen auch C/C++-Compiler für die Zielarchitektur bereitstellen CC_FOR_TARGET und CXX_FOR_TARGET wie beschrieben in golang.org/cmd/cgo. Ich habe jedoch keine spezifischen Ratschläge zum Erstellen für Windows unter OSX.

    – James Henstridge

    17. Oktober 2016 um 9:13 Uhr

  • Wie würdest du es unter Windows machen? Vor allem wofür der Ersatz wäre pthread?

    – Royi

    18. April 2021 um 12:18 Uhr

  • @Royi: Es ist Ewigkeiten her, seit ich für Windows entwickelt habe. Wenn Sie normalerweise kein spezielles Compiler-Flag benötigen, um ein C-Programm zu erstellen, das Threads verwendet, müssen Sie hier wahrscheinlich auch nichts Besonderes tun.

    – James Henstridge

    19. April 2021 um 15:44 Uhr

1407880cookie-checkVerwendung von Go-Code in einem bestehenden C-Projekt

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy