Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/tekintian/go-work-with-c-cpp
Go work with C/C++ , cpp .so, .a make demo, Golang调用 c/c++使用示例
https://github.com/tekintian/go-work-with-c-cpp
Last synced: about 9 hours ago
JSON representation
Go work with C/C++ , cpp .so, .a make demo, Golang调用 c/c++使用示例
- Host: GitHub
- URL: https://github.com/tekintian/go-work-with-c-cpp
- Owner: tekintian
- Created: 2022-04-08T11:24:54.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2022-04-08T11:26:30.000Z (over 2 years ago)
- Last Synced: 2024-06-20T20:41:43.610Z (5 months ago)
- Language: Go
- Size: 2.15 MB
- Stars: 1
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Golang调用 c/c++使用示例
# Go语言调用C++语言需要先将c++代码编译生成动态库 .so 或者 静态库.a 后才能调用
## go 调用C代码
非常简单,直接在.go文件的头部使用注释声明c代码即可, 详见
[go中使用C语言](./c_work_in_go.go)## go调用C++ 动态库.so/静态库.a
go调用c++代码逻辑关键点在于c代码的入口必须要有 extern "C" 的声明, 这样go才能调用, 如:
- warpper.h
~~~h
#ifdef __cplusplus
extern "C" {
#endif// 这里定义你的对外暴露的接口方法即可在go中调用
void doSomething();//示例
// .....#ifdef __cplusplus
}
#endif#endif
~~~ps: 静态库 .a 文件生成后可以在go中通过制定库路径直接使用, 如:
~~~go
/*
#cgo CFLAGS: -I${SRCDIR}/cpp
#cgo LDFLAGS: -L${SRCDIR}/cpp -lwrapper -lstdc++
#include
#include
#include "cpp/wrapper.h"
*/
import "C"~~~
如果是动态库,则在调试的时候需要将库文件.so文件复制到你的程序的运行路径下或者系统的lib库文件中才能被加载,否则无法加载!!
## go C++ 动态库.so生成 go 编译运行
~~~sh
# 同时生成 hello.so 和 wrapper.so 并编译和运行 hello.go wrapper.go
sh build.sh
Name is Alex, age is 18
Name is Alex, age is 18
New Name is Tekin age is 19
~~~## c 调用 c++ 动态库生成
~~~sh
# 生成动态库 hello.so
sh build_hello.sh# 运行 hello.go 测试
go run test.go
~~~## cpp to lib 动态库包装类 .so 生成
~~~sh
# 生成动态库 wrapper.so
sh build_wrapper.sh
cd ..
go run wrapper.go~~~
## 参数说明
-fpic ( pic:position independent code位置无关码)用于编译阶段,产生的代码没有绝对地址,全部用相对地址,满足了共享库的要求,共享库被加载时地址不是固定的。如果不加-fpic ,那么生成的代码就会与位置有关,当进程使用该.so文件时都需要重定位,且会产生成该文件的副本,每个副本都不同,不同点取决于该文件代码段与数据段所映射内存的位置。
CFLAGS: 指定头文件(.h文件)的路径,如:CFLAGS=-I/usr/include -I/path/include。同样地,安装一个包时会在安装路径下建立一个include目录,当安装过程中出现问题时,试着把以前安装的包的include目录加入到该变量中来。
LDFLAGS:gcc 等编译器会用到的一些优化参数,也可以在里面指定库文件的位置。用法:LDFLAGS=-L/usr/lib -L/path/to/your/lib。每安装一个包都几乎一定的会在安装目录里建立一个lib目录。如果明明安装了某个包,而安装另一个包时,它愣是说找不到,可以抒那个包的lib路径加入的LDFALGS中试一下。
需要注意的是,“-I dir”和“-L dir”都只是指定了路径,而没有指定文件,因此不能在路径中包含文件名。
另外值得详细解释一下的是“-l”选项,它指示Gcc去连接库文件libsunq.so。由于在Linux下的库文件命名时有一个规定:必须以lib三个字母开头。因此在用-l选项指定链接的库文件名时可以省去lib三个字母。也就是说Gcc在对”-lsunq”进行处理时,会自动去链接名为libsunq.so的文件。
告警和出错选项
-Wall 允许发出Gcc提供的所有有用的报警信息## go c 数据转换
go语言和C语言不同,无法直接通过( *_Ctype_char)的方式进行强制类型转换。但是可以通过 unsafe.Pointer 进行进行指针类型的转换。
示例如下:
~~~go
var ret C.int = 0
var key string = "1234567811111111"
var inData string = "1111111122222222"//对应C语言中的void*
var pContext unsafe.Pointervar nKeynum C.int = 1
//将go语言中的string转换成*C.char类型
var pKey = (C.CString(key))
var nKeyLen = C.uint(len(key))var pInData = C.CString(inData)
var nInDataLen = C.uint(len(inData))var pOutData *C.uchar
var pOutDataLen *C.uint//将*C.char转换成*C.uchar类型
var pKey2 = (*C.uchar)(unsafe.Pointer(pKey))
var pInData2 = (*C.uchar)(unsafe.Pointer(pInData))
~~~