This is a creation in Article, where the information may have evolved or changed.
Prerequisites:
Learn the basics and basic usage of the Go language and C language.
First, what is CGO
To put it simply, CGO is a way to use C language code in the Go language.
Second, why should have CGO
C language After decades of development, enduring, all aspects of the open source code, close-sourced library has been very rich. This is undoubtedly a huge treasure, for a modern programming language, how to use the ready-made C code is very important.
Third, how to use
3.1 System Configuration
To use CGO, you must have GCC on your computer and add the directory where the GCC compiler's executable is located to the environment variable in path. For example, my gcc.exe is under C:\mingw64\bin, so I want to add the C:\mingw64\bin directory to path.
3.2 C Fake Bag
We know that the go language is a logical unit of package code. If you want to use C code in the Go Code, set up a separate "package" for the C code and import it:
Import "C"
C is a fake package, the nature of the package it also generally has. For example, you can use the variable or type in the same way as "package name. Symbol Name".
var n c.int
This line of code defines a C-language variable of type int, with the
var conn net. Conn
Defines a net. There are no grammatical differences in variables of type Conn.
If you are next to the import "C" line, add successive lines of comments, write C code in the comments, the C code as the contents of the C package. For example:
/*int PlusOne (int n) {return n + 1;} */import "C"
You can call the PlusOne function in the go code, for example:
/* #include <stdio.h>*/import "C"
The functions in the header file stdio.h can be called in the Go code.
In addition, you can put your C source file in the same directory where you want to use the go source file, and then include the header file (include) in the C package. For example, I have C source file ys_origin.c and header file Ys_origin.h, and I want to invoke the function in Ys_origin.c in Ys_origin.go, then I can do this:
/*include "Ys_origin.h" */import "C" func funcone (a int, b string) error {//... C.levelup ()//...}
The specific usage is explained below.
Iv. Specific Introduction
C-language data structures have numeric types (integers and floating-point numbers), functions, arrays, pointers, structs, unions, and many third-party library API functions require a fallback function. That's one by one of the way.
4.1 Variables (global variables)
It is easy to use global variables in C, as long as "c. Variable name" is available.
/*int g_a = 7;*/import "C" func TestVar () {fmt. PRINTLN (C.G_A)//7 c.g_a = FMT. PRINTLN (C.G_A)//The var n int32 n = Int32 (c.g_a) + one FMT. PRINTLN (n)//53}
It is worth noting that go does not think that C.int is the same type as int32 or int, so it is not possible to assign a variable of type c.int directly to a variable of type int32, and if you want to do this, you must do a type conversion.
4.2 Functions
Use "C. Function name" to invoke the function.
/*int Sum (int a, int b) {return a + B;} */import "C" func testfunction () {var a int32 = a var b int32 = var s int32 = Int32 (C.sum (C.int (a), C.int (b)) ) FMT. PRINTLN (s)//56}
4.3 arrays
The usage of the array is the same as the variable. The code uses the C99 array initialization method.
/*int a[10] = {[2] = 7, [4] =, [] = 241};*/import "C" func Testarray () {for _, V: = Range C.A {fmt. Printf ("%d", V)//0 0 0 0 0 241 0 0} fmt. Printf ("\ n") c.a[5] = the FMT. Println (C.a[5])//100}
4.4 Hands
With the int* type of pointer p in C code, you can get the value of the variable it points to by using *C.P (same as the use of pointers in C), and *C.P can modify the value of the variable it points to.
Go for security reasons, *a and *b two pointers are not allowed to convert directly to each other. If you want to convert the pointer of C to go, you must use the pointer type in the unsafe package as the medium. Any pointer type can be converted to unsafe. Pointer, and vice versa. As unsafe as the package name shows, it is unsafe. Set P to a b* type of c pointer, and convert it to the *t type of Go pointer by:
(*t) (unsafe. Pointer (C.P))
It is important to note that T occupies the size of the memory can not exceed B, or there may be "memory can not be read" and other unexpected circumstances.
/*int B = 6;int *p = &b;*/import "C" func Testpointer () {fmt. Println ("b =", c.b)//b = 6 *C.P = fmt. Println ("b =", c.b)//b = P: = (*int32) (unsafe. Pointer (C.P)) *p = Fmt. Println ("b =", c.b)//b = 22}
4.5 Structural bodies
After you define the struct type T in C code, you will see the c.struct_t instead of the c.t in the Go code. Of course, if the structure of a TypeDef, you do not have to write that "struct_".
/*struct point_alpha{int x; int y;}; typedef struct _point_beta{int x; int y;} Point_beta;*/import "C" func teststruct () {var pa c.struct_point_alpha pa.x = 6 pa.y = fmt. PRINTLN (PA)//{6} var pb C.point_beta pb.x = Pb.y = -10 fmt. Println (PB)//{33-10}}
4.6 Consortium
The use of C's union in Go is relatively rare and cumbersome, as go treats the Union of C as a byte array. For example, the following consortium Large_integer is considered [8]byte.
typedef long LONG;TYPEDEF unsigned long dword;typedef long long longlong;typedef union _large_integer {struct { DWORD LowPart; LONG Highpart; }; struct {DWORD lowpart; LONG Highpart; } u; Longlong QuadPart;} Large_integer, *plarge_integer;
So, if a C function has a parameter of type Large_integer, we can give it a [8]byte type argument, and vice versa.
So, if a C function requires a union, we should construct a byte array as an argument.
/*typedef long long;typedef unsigned long dword;typedef long long longlong;typedef union _large_integer { struct { DWORD LowPart; LONG highpart; }; struct { DWORD LowPart; LONG HighPart; } u; longlong quadpart;} &NBSP;LARGE_INTEGER,&NBSP;*PLARGE_INTEGER;VOID&NBSP;AAA (Large_integer li) { Li.u.lowpart = 1; li.u.highpart = 4;} */import "C" func testunion () { var li c.large_integer // Equivalent to: var li [8]byte var b [8]byte = li // correct, because [8]byte and C.large_integer same c.aaa (b) // parameter type is Large_integer , you can receive [8]BYTE&NBSP;&NBSP;&NBSP;&NBSP;LI[0]&NBSP;=&NBSP;75&NBSP;&NBSP;&NBSP;&NBSP;FMT. Println (LI) // [75 0 0 0 0 0 0 0] li[4] = 23 showbytearray (LI) // parameter type is [8]byte, can receive C.large_integer}func showbytearray (B [8]byte) { fmt. Println (b)}
4.7 callback function
Functions can be considered as a piece of data in memory, and the function name of the C language represents the first address of the function. Passing a callback function to a function actually passes through the first address of a function. To do this, we need the following two functions:
Syscall. Newcallbacksyscall.newcallbackcdecl
The arguments for both functions are a interface{}, and the return value is a uintptr. Although they accept parameters of type interface{}, they must pass a go function, and the return value of the incoming go function must be the same size (size) as UIntPtr. they generate a C function (another piece of data in memory) based on a Go function (a section of data in memory) and return the first address of the C function. The difference between the two is that the C function generated by the former conforms to the __stdcall calling convention, and the latter generates a C function that conforms to the __cdecl calling convention.
After getting the first address of the function, it is not possible to pass it directly to the C function, since C's pointer to the function is treated as *[0]byte in go, so it needs to be converted.
C Code:
#include <stdint.h> #ifndef null#define NULL ((void*) 0) #endiftypedef uintptr_t (__stdcall* girl_proc) (unsigned (int), typedef uintptr_t (__cdecl* girl_proc_cdecl) (unsigned int), unsigned int Func1 (unsigned int n, girl_proc gp) {if (GP = = NULL) {return 0; } return (unsigned int) ((*GP) (n));} unsigned int Func2 (unsigned int n, girl_proc_cdecl gp) {if (GP = = NULL) {return 0; } return (unsigned int) ((*GP) (n));}
Go code:
The second parameter type of C.FUNC1 is a function, so you pass in a *[0]byte.
V. Comprehensive examples
is writing.
Vi. Practice
I will make some exercises in the future.