Go如何调用C++静态库,保姆级别教程来了!!! 最近因为工作需要,需要使用Go程序调用C及C++中一些库,网上的文章比较凌乱,有些已经过时,踩了许多坑,最终完成了集成,这里我写了一个完整的集成示例,方便大家快速集成,也避免踩坑!
1.环境说明
| 序号 | 项目 | 版本 | 说明 |
|---|---|---|---|
| 1 | Go | 1.19.7 | |
| 2 | g++ | MinGW-W64- 8.1.0 | |
| 3 | cmake | 3.26.4 | C++编译工具 |
| 4 | ninja | 1.10.2 | C++编译工具 |
| 5 | Goland | 2023.2.4 | Go开发工具 |
| 6 | CLion | 2023.2.2 | C++开发工具 |
| 7 | Windows | 11 | 开发操作系统 |
2.流程说明
Go如何调用C++库,主要分为3步:
1)制作C++静态库
2)创建Go程序
3)在Go应用中调用C++静态库
3.制作C++静态库
示例中,我们使用C++编写了一个加法和减法运算的函数,并将其编译成静态库,提供给Go程序调用
3.1文件清单
├── build --编译目录
├── CMakeLists.txt --cmake编译文件
├── cpp_test.h --头文件
└── cpp_test.cpp --源文件
3.2文件源码
3.2.1 cpp_test.h
#ifndef FATHER_CPP_TEST_H
#define FATHER_CPP_TEST_H
#ifdef __cplusplus
extern "C" {
#endif
int sub(int a,int b);
int add(int a,int b);
#ifdef __cplusplus
}
#endif
#endif //FATHER_CPP_TEST_H
3.2.2 cpp_test.cpp
#include "cpp_test.h"
int sub(int a,int b){
return a-b;
}
int add(int a,int b){
return a+b;
}
3.2.3 CMakeLists.txt
cmake_minimum_required(VERSION 3.22)
project(hello_lib)
set(CMAKE_CXX_STANDARD 11)
add_library(cpp_test STATIC cpp_test.cpp)
3.3 编译过程
编译步骤:
# 1. 如果build目录不存在,自行创建,然后进入build目录
cd build
# 2. 使用cmake编译工具生成文件,cmake
cmake .. -G Ninja
# 3. 使用ninja编译工具进行最终编译
ninja
完成输出:
cd build
cmake .. -G Ninja
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/mingw64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (1.3s)
-- Generating done (0.0s)
-- Build files have been written to: x:/cpp_test/build
ninja.exe
[2/2] Linking CXX static library libcpp_test.a
4.编写Go程序
这里使用一个main程序演示调用C++静态库过程
4.1 文件清单
完整的Go程序目录结构:
├── go.mod --go mod文件
├── include --头文件目录
│ └── cpp_test.h --头文件
├── lib --静态库文件目录
│ └── libcpp_test.a --静态库文件
└── main.go --Go程序
- 将C++库中的cpp_test.h头文件,存放至include文件夹中
- 将libcpp_test.a库文件,存放至lib文件夹中
4.2文件源码
4.2.1 main.go
package main
/*
#cgo CFLAGS: -I./include
#cgo LDFLAGS: -L./lib -lcpp_test -lstdc++
#include "cpp_test.h"
*/
import "C"
import "fmt"
func main() {
fmt.Println(C.sub(C.int(5), C.int(1)))
fmt.Println(C.add(C.int(1), C.int(4)))
}
说明:
1、import "C" 是启用Cgo,以及cgo配置,头文件,C函数
2、需要调用的C语言的内容使用/**/注释起来,放在import "C"之前
3、其中有两个#cgo命令,分别是编译和链接参数
#cgo CFLAGS: -I/user/local/include //库对应头文件所在的目录加入头文件检索路径
#cgo LDFLAGS: -L/user/local/lib -l库 //库所在目录加为链接库检索路径
4.3 执行输出
示例程序中,我们使用分别调用C++库的加法运行和减法运算
~$ ls
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2023/11/2 14:30 include
d---- 2023/11/2 14:30 lib
-a--- 2023/11/2 11:41 22 go.mod
-a--- 2023/11/2 14:45 230 main.go
~$ go run .
4
5
5.扩展信息
因Go与C中语言数据类型有差别,我们在调用C函数需要进行类型转换,Golang 和 C 的基本数值类型转换对照表如下: