This is the 30th day of my participation in the August Text Challenge.More challenges in August
CGO learning 2, basic data type conversions 2 and function calls
The data type conversion involved in CGO includes the following:
- Numeric types
- String and slice type
- Struct, union, enumeration type ‘
- An array type
- Pointer types
- Conversions between arrays and Pointers
- Transitions between slices and slices
The first three have been sorted out in the last essay, so continue
An array type
C language:
- An array of
In C, the array name corresponds to a pointer to a specific type of memory of a specific length, but this pointer cannot be modified
A C string is an array of type char. The length of the string depends on the position of the terminating NULL character
- string
Is an array of type char
- slice
C has no concept of slicing
In the GO language:
- An array of
An array is a value type, and the length of an array is part of the array type
- string
A block of read-only byte memory of definite length
- slice
Is a simple dynamic array
As can be seen from the above, the conversion of arrays, slices and strings between C and GO languages can be the conversion of Pointers and the length of memory pointed to by Pointers
CGO officially provides us with the following five functions for the mutual conversion between C language and GO language:
- func C.CString(string) *C.char
CString Clone the go String into a C format String. The cloned String is created using malloc in C language. Therefore, we have used up this function and need to manually free the memory
- func C.CBytes([]byte) unsafe.Pointer
C.CBytes is used to clone and convert the input array (slice) of the go byte type into Pointers in C language. Pointers are arrays that need to be allocated space and manually released when not in use
- func C.GoString(*C.char) string
C.GoString clone C string into GO string, GO itself will free memory
- func C.GoStringN(*C.char, C.int) string
C. Stringn, converts a string of C length to a string of GO, which will free memory itself
- func C.GoBytes(unsafe.Pointer, C.int) []byte
C. gobytes convert arrays of C into slices of GO
Summary:
A set of functions provided by the government above, GO language and C language conversion are achieved by cloning
GO to C
C uses malloc to open up memory in C’s own space, so we need to free it up when we don’t need it
C. turn to GO
Again by cloning, but GO has its own memory management and does not require us to manually free memory
Advantages of the above functions
- In the way of cloning conversion, memory is opened up in their own language, memory management is simple
Disadvantages of the above functions
- Converting to each other requires extra memory, increasing the system overhead
Conversion between Pointers and Pointers
How to convert Pointers to Pointers in CGO?
C language:
Pointers are the soul of C language. In C language, different types of Pointers can be cast, and free conversion between Pointers is also the first important problem to be solved in CGO code
In the GO language:
The different types of conversions are very strict, and any warning message that might appear in C might be an error in Go.
Pointers to different types in GO are forbidden to be converted, but CGO breaks that barrier by using the unsafe.pointer type as a bridge
For example,
var a *A
var b *B
b = (*b)(unsafe.Pointer(a)) // *A => *B
a = (*a)(unsafe.Pointer(b)) // *B => *A
Copy the code
Conversion between values and Pointers
How to convert values and Pointers in CGO?
In the GO language:
It is forbidden to convert numeric types directly to pointer types
But with cgo, we have a special uintptr for the unsafe.Pointer type in Go, which we still use as a bridge to convert to our purpose Pointer
For example, how do we convert a value int32 in GO to a pointer in C?
As mentioned above, we’ll use this bridge to transform int32 to uintptr, then to uint. pointer, and finally to char for C
Transitions between slices and slices
How to convert slices from slice to slice in CGO?
To convert slices from slice to slice, use the data structure provided by the Reflect package in GO,
Because the array or slice in GO is no longer a pointer, we need to use the data structure in Reflect to convert it, as follows:
// Its reference is not garbage collected, so the program must use the correct type of pointer to the underlying data
type StringHeader struct {
Data uintptr
Len int
}
// Its reference is not garbage collected, so the program must use the correct type of pointer to the underlying data
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
Copy the code
How to convert slice A into slice B?
We can do this by constructing an empty slice
var p []int
var q []string
pk := (*reflect.SliceHeader)(unsafe.Pointer(&p))
qk := (*reflect.SliceHeader)(unsafe.Pointer(&q))
Copy the code
The empty slice is then filled with the original data, and attention should be paid to the calculation and assignment of len and CAP
pk.Data = qk.Data
pk.Len = qk.Len * unsafe.Sizeof(q[0]) / unsafe.Sizeof(p[0])
pk.Cap = qk.Cap * unsafe.Sizeof(q[0]) / unsafe.Sizeof(p[0])
Copy the code
A function call
The basic function calls we demonstrated in the last article, let’s look at the others
- How does the return value of the C function itself apply in GO
How does the return value of the C function itself apply in GO
Let’s write a C function that returns a value, and then GO calls it:
C language does not support multiple return results, but GO language support return a result, CGO inside we can use
standard library errno macro used to return error status
package main
/* #include
static int testadd(int a, int b) { if (a < 0){ errno = EINVAL; return 0; } return a+b; } * /
import "C"
import "fmt"
func main(a) {
v0, err0 := C.testadd(2 -.1)
fmt.Println(v0, err0)
v1, err1 := C.testadd(1.2)
fmt.Println(v1, err1)
}
Copy the code
The result is as follows:
0 invalid argument
3 <nil>
Copy the code
If C’s function returns no value, we can do the same.
For example, it could look like this
V, _ : = C.x xx (FMT). The Printf (" % # v ", v) / / output as the main _Ctype_void {} FMT. Println (C.x xx ()) / / output [0] to [] 0 long array type byteCopy the code
We found that the V OID type of C language corresponds to the _Ctype_void type in the current main package
Constant dropping wears away a stone
References:
GO Advanced Programming
Welcome to like, follow and favorites
Friends, your support and encouragement, I insist on sharing, improve the quality of the power
All right, that’s it for this time
Technology is open, our mentality, should be more open. Embrace change, live in the sun, and strive to move forward.
I am Nezha, welcome to like, see you next time ~