详解如何在Go语言中调用C源代码_第1页
详解如何在Go语言中调用C源代码_第2页
详解如何在Go语言中调用C源代码_第3页
详解如何在Go语言中调用C源代码_第4页
详解如何在Go语言中调用C源代码_第5页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第详解如何在Go语言中调用C源代码目录开坑说明内嵌形式外置的C代码1.构建libauth.a静态库2.对main.go稍加修改3.编译

开坑说明

最近在编写客户端程序或与其他部门做功能集成时多次碰到了跨语言的sdk集成,虽说方案很多诸如rpc啊,管道啊,文件io啊,unixsocket啊之类的不要太多,但最完美的基础方式还是让程序与sdk结合到一起(个人观点,不喜勿喷),顺便研究了下在go调用标准c接口的种种方法与坑,内容不少,有空便慢慢更新了。

内嵌形式

先让我们来看一个最简单的cgo实例

packagemain

//#includestdio.h

import"C"

funcmain(){

C.puts(C.CString("HelloWorld"))

输出

HelloWorld

通过C包调用了c中常见的puts函数同时传入通过C.Cstring把go中string转化为的cstring(相当于char*)。其实C这个并不是一个包,而是通过importC语句启用了go编译器cgo相关的功能让gcc也参与到了编译中。这种方式通过紧贴在importC语句上面的注释中编写c代码并在后续代码中使用C对象调用。当然也可以通过这种方式调用自定义的c函数。

packagemain

import"C"

/*#includestdio.h

voidsay_hello_with_name(char*name){

printf("hello%s\n",name);

import"C"

funcmain(){

C.say_hello_with_name(C.CString("oscar"))

}

输出

hellooscar

外置的C代码

内置的C代码固然很方便,但用到cgo大多数的使用场景是我有一个需要复用的c代码库,像是c++的stl库亦或者是linuxc中的什么已经封装好的第三方依赖。这些时候便需要外置一些c的文件.h.c.cpp之类与.go文件混编。先看一个最简单的例子(调用linux的系统账户认证)。

//auth.h

intauth(char*user,char*passwd);

//auth.c

#includeshadow.h

#includestdio.h

#includeunistd.h

intauth(char*user,char*passwd){

char*obtpwd;

structspwd*spasswd;

spasswd=getspnam(user);

obtpwd=crypt(passwd,spasswd-sp_pwdp);

if(strcmp(spasswd-sp_pwdp,obtpwd)==0)

return0;

elsereturn1;

}

//main.go

packagemain

#cgoLDFLAGS:-lcrypt

#include"auth.h"

import"C"

import"fmt"

funcmain(){

varusername,passwordstring

fmt.Println("Pleaseenteryourusernameandpassword:")

_,_=fmt.Scanln(username,password)

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

fmt.Println(rst)

}

保证上述三个文件在同一个go工程目录下运行gobuild-omain构建工程。#cgoLDFLAGS:-lcrypt这个一行是cgo给gcc的编译参数,相关的编译参数与连接参数有空了在后面的文章里说明,-lcrypt表示编译时需要去连接libcrypt这个库。

注意,这种cgo混编的方式个人是不建议的,cgo对外置c代码片构建支持非常差,我无法在cgo中通过编译参数指定c代码片的搜索路径(头文件倒是没啥问题),这也就意味着当项目被调用的c代码片都得在项目根目录下,这可太糟糕了。个人觉得如果有大量的外部依赖c语言的库请分开编译,c库使用gcc编译成静态或动态库在让go在编译时连接为好,写个makefile分开分步编译也不是什么麻烦事,还是上面的例子,让我们把编译的过程稍加修改。

1.构建libauth.a静态库

gcc-c-oauth.o-lcryptauth.c

arrcslibauth.aauth.o

得到libauth.a

2.对main.go稍加修改

packagemain

#cgoCFLAGS:-I./

#cgoLDFLAGS:-L.-lauth-lcrypt

#include"auth.h"

import"C"

import"fmt"

funcmain(){

varusername,passwordstring

fmt.Println("Pleaseenteryourusernameandpassword:")

_,_=fmt.Scanln(username,password)

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

fmt.Println(rst)

此处修改主要是新增了libauth.a静态库的链接参数

3.编译

gobuild-omainmain.go

可以把上述的步骤整下写个简单的makefile

.PHONY:all

all:main

libauth.a:auth.c

gcc-c-oauth.o-lcryptauth.c

arr

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论