This is a creation in Article, where the information may have evolved or changed. After decades of development in the C language, a wide variety of ready-made libraries are already plentiful. With CGO, you can use the C language code in the go language to make the most of the existing "wheels".
All the code in this document is debugged in the following environment:
Windows 8.1 64-bit
Go 1.3.3 64-bit
GCC 4.8.1 64-bit
To use CGO, import the C "package":
Import "C"
This line of code is next to the comments of several successive lines, writing C code in these comments. For example:
/*
int PlusOne (int n)
{
return n + 1;
}
*/
Import "C"
We know that if you want to reference a symbol in a package, you need to use the "package name. Symbol Name" method, C "Package" is also the case, for example: C.int, C.getwindowlongptr.
The following is a method of using C language variables, functions, structs, unions, callback functions, and dynamic link libraries (library,dll).
Variable
Function
Structural body
Complex
callback function
Dll
1. Variables
The use of C variables is simple, for example, to use int, as long as the go code to write C.int.
Package Main
Import (
"FMT"
)
Import "C"
Func Main () {
var n c.int
n = 5
Fmt. PRINTLN (n)//5
var M1 int
Go does not think C.int is the same type as int, Int32, etc.
So it has to be converted.
m1 = Int (n + 3)
Fmt. PRINTLN (M1)//8
var m2 int32
M2 = Int32 (n + 20)
Fmt. Println (m2)//25
}
2. Functions
It is not difficult to invoke the C function in go.
Package Main
Import (
"FMT"
)
/*
int PlusOne (int n)
{
return n + 1;
}
*/
Import "C"
Func Main () {
var n int = 10
var m int = Int (C.plusone (C.int (n)))//type to convert
Fmt. PRINTLN (m)//11
}
3. Structural Body
Package Main
Import (
"FMT"
)
/*
typedef struct _POINT
{
Double X;
Double y;
}point;
*/
Import "C"
Func Main () {
var p c.point
p.x = 9.45
P.Y = 23.12
Fmt. PRINTLN (p)//{9.45 23.12}
}
4. Consortium
The use of C's union in Go is a rare and strange thing, and a little cumbersome, because 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.
Package Main
Import (
"FMT"
)
/*
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;
void Show (Large_integer li)
{
Li.u.lowpart = 1;
Li.u.highpart = 4;
}
*/
Import "C"
Func Main () {
var li c.large_integer//equivalent to: Var li [8]byte
var b [8]byte = li//correct, because [8]byte and C.large_integer are the same
C.show (b)//parameter type Large_integer, can receive [8]byte
Li[0] = 75
Fmt. Println (LI)//[75 0 0 0 0 0 0 0]
LI[4] = 23
Test (LI)//parameter type [8]byte, can receive C.large_integer
}
Func Test (b [8]byte) {
Fmt. Println (b)
}
5. Callback function
Some parameters of the C function are callback functions, for example:
typedef uint_ptr (__stdcall* girl_proc) (int);
typedef uint_ptr (__cdecl* girl_proc_cdecl) (int);
Uint_ptr Func1 (int n, Girl_proc GP)
{
if (gp = = NULL)
{
return 0;
}
Return (*GP) (n);
}
Uint_ptr Func2 (int n, girl_proc_cdecl GP)
{
if (gp = = NULL)
{
return 0;
}
Return (*GP) (n);
}
The Syscall package has the following two functions:
Syscall. Newcallback
Syacall. Newcallbackcdecl
Where the first function receives a go function (the return value of the GO function must be only one, and the type is uintptr), and generates a C function that __stdcall the calling convention, and returns the address of the generated function as a uintptr; the second function is similar in effect. But the calling convention for the generated function is __cdecl.
A notable problem is that the pointer to the function of C is considered *[0]byte in go, so it is necessary to convert it. Here is a demonstration of the use of __stdcall calling convention functions, __cdecl similar.
Package Main
Import (
"FMT"
"Syscall"
"Unsafe"
)
/*
#define Win32_lean_and_mean
#include <windows.h>
typedef uint_ptr (__stdcall* girl_proc) (int);
typedef uint_ptr (__cdecl* girl_proc_cdecl) (int);
Uint_ptr Func1 (int n, Girl_proc GP)
{
if (gp = = NULL)
{
return 0;
}
Return (*GP) (n);
}
Uint_ptr Func2 (int n, girl_proc_cdecl GP)
{
if (gp = = NULL)
{
return 0;
}
Return (*GP) (n);
}
*/
Import "C"
Func Girlproc (n int32) uintptr {
return UIntPtr (n + 97)
}
Func Main () {
GP: = Syscall. Newcallback (Girlproc)
Fmt. Println (GP)
GOP: = (*[0]byte) (unsafe. Pointer (GP))
var t c.uint_ptr = c.func1 (c.int), GOP
Fmt. PRINTLN (t)//126
}