Seite wählen

CGo. Halb C – halb Go.

von | Jan 24, 2019 | C++, Golang

In meinem letzten Blog-Post, The way to Go, habe ich bereits einige Vorteile der Programmiersprache Go aufgezeigt. Und als ob es nicht schon genug wäre, dass man beim Umstieg auf Go nicht gleich das Kind mit dem Bade ausschütten muss: Ein einzelnes Programm muss nicht mal komplett in Go geschrieben sein…

Multilingual unterwegs

Ich arbeite für einen deutschen IT-Dienstleister, aber beim recherchieren von Lösungen für Kundenprobleme muss ich die russischen Quellen nicht erst ins Deutsche übersetzen, sondern kann direkt mit ihnen arbeiten. Genau so kann bspw. ein Go-Programm direkt von C-Bibliotheken Gebrauch machen – und umgekehrt. Vorausgesetzt, die Schnittstellen beschränken sich auf den kleinsten gemeinsamen Nenner.

Was wäre das auch wirtschaftlich für ein Fass ohne Boden wenn sämtliche benötigte Bibliotheken erst in Go neu geschrieben werden müssten. Umso mehr wundert es mich, dass so manche Datenbank-Treiber doch komplett neu geschrieben wurden…

Good programmers know what to write.
Great ones know what to rewrite (and reuse).

Eric Steven Raymond, The Cathedral and the Bazaar

Multilingual in der Praxis

Ich bin zwar kein Fernsehkoch, aber habe trotzdem schon mal was vorbereitet – eine extrem abgespeckte Version von go-linux-sensors:

package go_linux_sensors

/*
#include <stdio.h>
#include <string.h>
#include <sensors/sensors.h>
#include <sensors/error.h>

typedef const char cchar;

#cgo LDFLAGS: -lsensors
*/
import "C"

import (
	"reflect"
	"unsafe"
)

type Error struct {
	errnr C.int
}

func (e Error) Error() string {
	return cStr2str(C.sensors_strerror(e.errnr))
}

func Init() error {
	if err := C.sensors_init((*C.FILE)(nil)); err != C.int(0) {
		return Error{err}
	}

	return nil
}

func Cleanup() {
	C.sensors_cleanup()
}

func GetLibsensorsVersion() string {
	return cStr2str(C.libsensors_version)
}

func cStr2str(cStr *C.cchar) string {
	slen := int(C.strlen(cStr))

	bridge := reflect.SliceHeader{
		Data: uintptr(unsafe.Pointer(cStr)),
		Len:  slen,
		Cap:  slen,
	}

	return string(*(*[]byte)(unsafe.Pointer(&bridge)))
}

Diese schlägt eine Brücke zu libsensors, um die Hardware-Sensoren auszulesen.

Direkt nach dem Package folgt auch schon der Import des ominösen Pakets “C”. Dieses enthält sämtliche C-Standard-Datentypen und alle Datentypen und Funktionen, die über Header-Dateien im Kommentar direkt darüber eingebunden wurden. Ja, richtig, in diesem “magischen” Kommentar lässt sich nahezu beliebiger C-Code unterbringen, um auf jenen im Go-Code zuzugreifen. Des weiteren lassen sich die tatsächlichen Bibliotheken mit “#cgo LDFLAGS:” automatisch linken. Bei höheren Mengen an Code/Includes bevorzuge ich persönlich eine extra Header-Datei statt einem langen Kommentar.

Etwas weiter unten ruft Init() auch schon sensors_init() auf – als wäre es eine gewöhnliche Go-Funktion im Paket C. Und auch die Datentypen lassen sich verwenden als seien es die eigenen – wovon Error fleißig Gebrauch macht.

Lediglich cStr2str() macht einen etwas unorthodoxen Eindruck… aber hey – es funktioniert. 😉

Jeder gesparte Euro zählt…

… und jede wiederverwendete Zeile Code. Wir bei NETWAYS wissen das zu schätzen und arbeiten dementsprechend effizient – an euren Projekten!

Alexander Klimov
Alexander Klimov
Senior Developer

Alexander hat 2017 seine Ausbildung zum Developer bei NETWAYS erfolgreich abgeschlossen. Als leidenschaftlicher Programmierer und begeisterter Anhänger der Idee freier Software, hat er sich dabei innerhalb kürzester Zeit in die Herzen seiner Kollegen im Development geschlichen. Wäre nicht ausgerechnet Gandhi sein Vorbild, würde er von dort aus daran arbeiten, seinen geheimen Plan, erst die Abteilung und dann die Weltherrschaft an sich zu reißen, zu realisieren - tut er aber nicht. Stattdessen beschreitet er mit der...
Mehr Beiträge zum Thema C++ | Golang

C++Go. Halb C++ – halb Go.

Scherz beiseite, die Go-Entwickler bieten noch keine Möglichkeit, C++-Bibliotheken ohne weiteres anzusprechen. Aber es geht ja auch mit weiteres. Das weitere besteht darin, dass C++-Funktionen mittels C-Bibliotheken gewrapped werden können. Und in meinem letzten...

DEV stories: Icinga Core trainees in the making

When my dev leads approached me with the idea to guide a trainee in the Icinga core topic, I was like ... wow, sounds interesting and finally a chance to share my knowledge. But where should I start and how can it be organized with my ongoing projects?   Prepare...

Generics waren gestern. Lang lebe Golangs Reflection!

Vor einiger Zeit habe ich die Programmiersprache Golang und all ihren Nutzen für die Entwickler vorgestellt. Zugegeben, eine in der Konkurrenz sehr verbreitete Funktionalität besitzt Go nicht: Generics. Und diese Funktionalität is noch dazu sehr gefragt. Allein das...

Modern C++ programming: Coroutines with Boost

We're rewriting our network stack in Icinga 2.11 in order to to eliminate bugs with timeouts, connection problems, improve the overall performance. Last but not least, we want to use modern library code instead of many thousands of lines of custom written code. More...

Veranstaltungen

Di 18

Icinga 2 Fundamentals Training | Online

Mai 18 @ 09:00 - Mai 21 @ 17:00
Jun 15

stackconf online

Juni 15 - Juni 17
Jun 22

Ansible Fundamentals Training | Online

Juni 22 @ 09:00 - Juni 24 @ 17:00
Jun 22

Kubernetes Quick Start | Online

Juni 22 @ 09:00 - 17:00
Jun 25

Ansible AWX (Tower) Training | Online

Juni 25 @ 09:00 - 17:00