introduce
使用golang
开发httpServer
非常方便,如果我们需要在c
程序中内嵌httpServer
,可以考虑使用go
来开发服务模块,然后编译成共享库供c
调用
code by go
code
1 | package main |
注意点:
需要引入
C
包,可以使用C
包中的GoString
将c
的字符串转换为go
的字符串需要导出的函数,需要使用
//export funcName
标识包内函数也可以导出
go
和c
两者的字符串内存布局不同,如果go
函数参数声明为go
的字符串类型,在c
中相当于一个结构体:1
2typedef struct { const char *p; ptrdiff_t n; } _GoString_;
typedef _GoString_ GoString;当要在
c
中调用go
函数时,需要手动构造字符串,而且还有内存安全的问题。
compile
动态共享库:运行时动态加载;如果运行时加载失败则报错
1
$ go build -buildmode=c-shared -o libtest.so main.go
编译完成之后将生成
libtest.so
和libtest.h
文件静态共享库:编译时静态链接到程序中;生成二进制文件较大
1
$ go build -buildmode=c-archive -o test.a main.go
编译完成之后将生成
test.h
和test.a
文件
use in c
code
在开始写代码之前,我们要先看一下生成的test.h
里面的内容:
1 | typedef struct { const char *p; ptrdiff_t n; } _GoString_; |
可以看到,.h
文件中包含了外部函数ServerRun
和wait
的声明
1 |
|
compile
静态共享库
1
$ gcc -pthread -o test main.c test.a
使用静态链接时,需要指定
-pthread
选项Link with the POSIX threads library. This option is supported on GNU/Linux targets, most other Unix derivatives, and also on x86 Cygwin and MinGW targets. On some targets this option also sets flags for the preprocessor, so it should be used consistently for both compilation and linking.
也可以动态加载
pthread
库1
$ gcc -lpthread -o test main.c test.a
动态共享库
1
$ gcc main.c -ltest -L. -I. -o test
-l
:声明使用到的动态共享库,比如libtest.so
,则这里传入test
-L
:在指定路径中查找共享库;也可以将.so
文件拷贝到默认共享库目录下-I
:在指定路径中查找.h
头部文件
编译之后生成test
文件,执行./test
,然后在访问http://localhost:8080
可以看到返回了Hi!
内容。
如果使用动态加载,运行前需要先将libtest.so
文件拷贝到动态加载库默认的加载路径中,或者将当前路径加到LD_LIBRARY_PATH
环境变量中。