C++ libraries with GO GO interface to C++ code, or vice versa. Advance cgo topics such as DLL-linking with cgo We're hiring 逐條審查(?) Interfacing C libraries with GO
that call C code. Ability to use existing C code Tool to generate code to access C library functions and global variables Interfacing C libraries with GO
Overview Go is a compiled language, not a scripting language. However, it does not support direct calling of functions written in C/C++. The cgo program may be used to generate wrappers to call C code from Go, but there is no convenient way to call C++ code. SWIG fills this gap. There are (at least) two different Go compilers. One is the gc compiler, normally invoked under the names 6g, 8g, or 5g. The other is the gccgo compiler, which is a frontend to the gcc compiler suite. The interface to C/C++ code is completely different for the two Go compilers. SWIG supports both, selected by a command line option. Reference SWIG and Go (http://www.swig.org/Doc2.0/Go.html) Interfacing C libraries with GO
Go present 啦!!! $ present 2014/04/11 14:55:59 Open your web browser and visit http://127.0.0.1:3999/ package main import "fmt" func main() { fmt.Println("Hello World") } Run Interfacing C libraries with GO
C code block you want to interface as comment block following with import "C" write some code $ go build xxxx.go run it $ ./xxxx Interfacing C libraries with GO
CFLAGS: -DPNG_DEBUG=1 // #cgo amd64 386 CFLAGS: -DX86=1 // #cgo LDFLAGS: -lpng If using makefile or ENV `CGO_CFLAGS`, `CGO_CPPFLAGS`, `CGO_CXXFLAGS`, `CGO_LDFLAGS` Interfacing C libraries with GO
cl lu ud de e < <s st td di io o. .h h> > # #i in nc cl lu ud de e < <s st td dl li ib b. .h h> > # #i in nc cl lu ud de e < <s st tr ri in ng g. .h h> > c ch ha ar r * * f fo or rm ma at t( (c ch ha ar r* * s s) ) { { char *buf; buf = malloc(strlen(s)); sprintf(buf, "%s", s); return buf; } */ import "C" Interfacing C libraries with GO
s : := = C C. .f fo or rm ma at t( (C C. .C CS St tr ri in ng g( (" "H He el ll lo o w wo or rl ld d\ \n n" ") )) ) defer C.free(unsafe.Pointer(cs)) fmt.Println(C.GoString(cs)) } Hello world Program exited. Run Kill Close Interfacing C libraries with GO
"C" package main /* #include "stdio.h" */ i im mp po or rt t " "C C" " func main() { C.printf(C.CString("Hello world\n")) } Run Interfacing C libraries with GO
code /* #include <stdio.h> e ex xt te er rn n v vo oi id d A AC CF Fu un nc ct ti io on n( () ); ; */ add export / // /e ex xp po or rt t A AG Go oF Fu un nc ct ti io on n func AGoFunction() { fmt.Println("Hello GO World") } Interfacing C libraries with GO
void ACFunction() { printf("Hello C World\n"); AGoFunction(); } command line $ go build $ ./goc Hello C World Hello GO World Interfacing C libraries with GO
nc cl lu ud de e < <o op pe en ns ss sl l/ /c cr ry yp pt to o. .h h> > #cgo CFLAGS: -I/usr/local/opt/openssl/include #cgo LDFLAGS: -L/usr/local/opt/openssl/lib -lcrypto */ func Version(t C.int) string { return C.GoString( C C. .S SS SL Le ea ay y_ _v ve er rs si io on n( (t t) )) ) } func main() { fmt.Println(Version(0)) } Run Interfacing C libraries with GO
#cgo CFLAGS: -I/usr/local/opt/openssl/include # #c cg go o L LD DF FL LA AG GS S: : / /u us sr r/ /l lo oc ca al l/ /o op pt t/ /o op pe en ns ss sl l/ /l li ib b/ /l li ib bc cr ry yp pt to o. .a a # # s st ta at ti ic c l li ib br ra ar ry y */ func main() { fmt.Println(Version(0)) } Run Interfacing C libraries with GO
go o p pk kg g- -c co on nf fi ig g: : o op pe en ns ss sl l # # p pk kg g- -c co on nf fi ig g g gi iv ve es s i in nf fo or rm ma at ti io on n # #c cg go o L LD DF FL LA AG GS S: : - -l lc cr ry yp pt to o # # o om mi it t d di ir re ec ct to or ri ie es s */ func main() { fmt.Println(Version(0)) } Run Interfacing C libraries with GO
/usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib (compatibility version 1.0.0, current version 1.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1) static-linked $ otool -L openssl_s openssl_s: /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib (compatibility version 1.0.0, current version 1.0.0) pkg-config $ otool -L openssl_pkg /usr/lib/libcrypto.0.9.8.dylib (compatibility version 0.9.8, current version 50.0.0) /usr/lib/libssl.0.9.8.dylib (compatibility version 0.9.8, current version 50.0.0) /usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1) Interfacing C libraries with GO
freed with C.free func C.CString(goString string) *C.char // C string to Go string func C.GoString(cString *C.char) string // C string, length to Go string func C.GoStringN(cString *C.char, length C.int) string // A new Go byte slice from a C array (pointer) func C.GoBytes(cArray unsafe.Pointer,length C.int) []byte Interfacing C libraries with GO
= N Ne ew w( () ) f fm mt t. .P Pr ri in nt tl ln n( (" "M Ma ax x m me es ss sa ag ge e l le en ng gt th h i is s : : " ", , m m. .S Si iz ze e( () )) ) plaintext := "I am plain text" fmt.Println("Plain: ", plaintext) c ci ip ph he er rt te ex xt t : := = m m. .R RS SA A_ _p pu ub bl li ic c_ _e en nc cr ry yp pt t( ([ [] ]b by yt te e( (p pl la ai in nt te ex xt t) )) ) fmt.Println("Cipher: ", string(ciphertext)) fmt.Println("Cipher in bytes: ", ciphertext) p pl la ai in n : := = m m. .R RS SA A_ _p pr ri iv va at te e_ _d de ec cr ry yp pt t( ([ [] ]b by yt te e( (c ci ip ph he er rt te ex xt t) )) ) fmt.Println("Decrypted: ", string(plain)) F Fr re ee e( (m m) ) } Run Interfacing C libraries with GO
#include <openssl/engine.h> // #cgo CFLAGS: -I/usr/local/opt/openssl/include // #cgo LDFLAGS: -L/usr/local/opt/openssl/lib -lcrypto import "C" import ( "fmt" "unsafe" ) type M struct { c ct tx x * *C C. .R RS SA A } Interfacing C libraries with GO
*from, unsigned char *to, RSA *rsa, int padding); in GO func (m *M) RSA_public_encrypt(plain []byte) []byte { cipher := (unsafe.Pointer)(C.malloc(C.size_t(C.RSA_size(m.ctx)))) defer C.free(unsafe.Pointer(cipher)) ret := C.RSA_public_encrypt( C C. .i in nt t( (l le en n( (p pl la ai in n) )) ), , / // / f fl le en n ( (* *C C. .u uc ch ha ar r) )( (& &p pl la ai in n[ [0 0] ]) ), , / // / f fr ro om m ( (* *C C. .u uc ch ha ar r) )( (c ci ip ph he er r) ), , / // / t to o m m. .c ct tx x, , / // / R RS SA A * *r rs sa a C C. .R RS SA A_ _P PK KC CS S1 1_ _P PA AD DD DI IN NG G) ) / // / p pa ad dd di in ng g return C.GoBytes(cipher, ret) } Interfacing C libraries with GO
*from, unsigned char *to, RSA *rsa, int padding); in GO func (m *M) RSA_private_decrypt(cipher []byte) []byte { p pl la ai in n : := = ( (u un ns sa af fe e. .P Po oi in nt te er r) )( (C C. .m ma al ll lo oc c( (C C. .s si iz ze e_ _t t( (C C. .R RS SA A_ _s si iz ze e( (m m. .c ct tx x) )) )) )) ) d de ef fe er r C C. .f fr re ee e( (u un ns sa af fe e. .P Po oi in nt te er r( (p pl la ai in n) )) ) ret := C.RSA_private_decrypt( C.int(len(cipher)), (*C.uchar)(&cipher[0]), (*C.uchar)(plain), m.ctx, C.RSA_PKCS1_PADDING) return C.GoBytes(plain, ret) } Interfacing C libraries with GO
= N Ne ew w( () ) f fm mt t. .P Pr ri in nt tl ln n( (" "M Ma ax x m me es ss sa ag ge e l le en ng gt th h i is s : : " ", , m m. .S Si iz ze e( () )) ) plaintext := "I am plain text" fmt.Println("Plain: ", plaintext) c ci ip ph he er rt te ex xt t : := = m m. .R RS SA A_ _p pu ub bl li ic c_ _e en nc cr ry yp pt t( ([ [] ]b by yt te e( (p pl la ai in nt te ex xt t) )) ) fmt.Println("Cipher: ", string(ciphertext)) fmt.Println("Cipher in bytes: ", ciphertext) p pl la ai in n : := = m m. .R RS SA A_ _p pr ri iv va at te e_ _d de ec cr ry yp pt t( ([ [] ]b by yt te e( (c ci ip ph he er rt te ex xt t) )) ) fmt.Println("Decrypted: ", string(plain)) F Fr re ee e( (m m) ) } Max message length is : 256 Plain: I am plain text Cipher: u��"�E��ժ`�0<�^C���7��H|��P�\?���Xĩ��gS��$RY`�MpH���px�M� [�����L��|�������c������dV��t"�j��w���A��A��-�=h�q�� zY�s#��~-��� �K���3�4��qP��ny'��0�̠ A��p�=0��-rAĞ�1G�leB�Y���p}\�@U�/ʨS���4�5�I?Y[ Cipher in bytes: [117 25 19 248 190 34 195 69 135 212 213 170 96 Decrypted: I am plain text Program exited. Run Kill Close Interfacing C libraries with GO