Call C source code \\basic Chapter 1 in GO

Embedded form

Let's take a look at the simplest example of cgo

package main

//#include <stdio.h>
import "C"

func main() {
	C.puts(C.CString("Hello World"))
}

output

Hello World

Call the common put function in C through "C package", and pass in the C string (equivalent to char *) that converts the string in go into C string through C.Cstring. In fact, "C" is not a package, but enables the go compiler cgo related functions through the import "C" statement, so that gcc also participates in the compilation. In this way, C code is written in the comments immediately above the import "C" statement, and C object calls are used in subsequent code. Of course, you can also call custom C functions in this way.

package main
import "C"

/*#include <stdio.h>

void say_hello_with_name(char * name){
	printf("hello %s\n", name);
}
 */
import "C"

func main() {
	C.say_hello_with_name(C.CString("oscar"))
}

output

hello oscar

External C code

Although the built-in C code is very convenient, most use scenarios of cgo are that I have a C code library that needs to be reused, such as the stl library of C + +, or the encapsulated third-party dependency in linux c. At these times, you need some external C files h .c .cpp and so on go file mix. Let's take a look at the simplest example (calling the system account authentication of linux).

// auth.h
int auth(char *user, char *passwd);
// auth.c
#include <shadow.h>
#include <stdio.h>
#include <unistd.h>

int auth(char *user, char *passwd){
    char *obtpwd;
    struct spwd *spasswd;

    spasswd = getspnam(user);
    obtpwd = crypt(passwd, spasswd->sp_pwdp);
    if(strcmp(spasswd->sp_pwdp, obtpwd) == 0)
    return 0;
    else return 1;
}

// main.go
package main

/*
#cgo LDFLAGS: -lcrypt

#include "auth.h"
*/
import "C"
import "fmt"

func main() {
	var username, password string

	fmt.Println("Please enter your username and password: ")
    _, _ = fmt.Scanln(&username, &password)

	rst := C.auth(C.CString(username), C.CString(password))
	fmt.Println(rst)
}

Ensure that the above three files run the go build -o main build project under the same go project directory# cgo LDFLAGS: -lcrypt this line is the compilation parameters cgo gives gcc. If the relevant compilation parameters and connection parameters are empty, it will be explained in the following article, - lcrypt means that libcrypt needs to be connected during compilation.
Note that this method of c-go mixed compilation is not recommended personally. cgo supports very poor construction of external c-chips. I can't specify the search path of c-chips in cgo through compilation parameters (header file is no problem), which means that when the c-chips called by the project have to be in the project root directory, it's too bad. Personally, I think if there are a large number of external libraries that depend on C language, please compile them separately. The C library is compiled into static or dynamic libraries using gcc. It's better to connect go during compilation. It's not troublesome to write a makefile for separate step-by-step compilation. Let's modify the compilation process slightly according to the above example.

1. Build libauth A static library

gcc -c -o auth.o -lcrypt auth.c
ar rcs libauth.a auth.o

Get libauth a

2. For main Go slightly modified

package main

/*
#cgo CFLAGS: -I./
#cgo LDFLAGS: -L. -lauth -lcrypt

#include "auth.h"
*/
import "C"
import "fmt"

func main() {
	var username, password string

	fmt.Println("Please enter your username and password: ")
    _, _ = fmt.Scanln(&username, &password)

	rst := C.auth(C.CString(username), C.CString(password))
	fmt.Println(rst)
}

The main modification here is the addition of libauth A link parameters of static library

3. Compilation

go build -o main main.go

You can complete the above steps and write a simple makefile

.PHONY : all

all: main

libauth.a: auth.c
	gcc -c -o auth.o -lcrypt auth.c
	ar rcs libauth.a auth.o

main: main.go libauth.a
	go build -o main main.go

clean:
	rm -f auth.o libauth.a main

This also makes the process of getting the product relatively simple and fast

Posted by Thundarfoot on Sat, 07 May 2022 09:37:06 +0300