精华内容
下载资源
问答
  • 我是通过golang调用c库,版本是 1.12.5,主要使用upsert接口,并发写入,高并发时达到上千,但发现运行一段时间后,就会core掉,信息如附件1.png所示, ![图片说明]...
  • CGO - GOLANG调用C库

    2018-07-08 10:25:48
    因此之前在用java时使用到了JNI调用C代码,那么Go语言则可使用CGO调用C语言代码。 当前就遇到了一个现实的场景,即我们使用go语言开发git hook,主要实现权限验证,大文件二进制验证等功能。它使用开源git2go,而...

          虽然C代码很难写,尤其是内存管理,但不得不承认,目前很多开源项目都还是用纯C编写的,我想主要还是执行效率高和商业发布时不容易反编译(次要)。因此之前在用java时使用到了JNI调用C代码,那么Go语言则可使用CGO调用C语言代码。

         当前就遇到了一个现实的场景,即我们使用go语言开发git hook,主要实现权限验证,大文件二进制验证等功能。它使用开源git2go,而git2go又是依赖c语言库libgit2,那么他们之间的调用方式正是使用CGO


        给个cgo的helloworld吧,不难,一看就能懂https://blog.csdn.net/win_lin/article/details/51734588

     

       然而真正的坑在于,使用cgo生成的hook可执行文件,是动态依赖外部的库,可以用ldd命令即可查看它动态依赖了好多系统的so库,因此如果生产环境是不同的linux环境则会遇到很多问题。以下给出几种解决方案

       1.每个环境都以源码重新编译。     -该方案不太现实,毕竟环境还需要装golang,gcc等等

       2.使用静态编译。  查了以下静态编译的方法是go build -ldflags -extldflags=-static ,并通过一系列环境变量指定库,头文件地址。

         指定库路径的方法https://blog.csdn.net/jaylong35/article/details/6132087

        pkgconfig引入环境变量https://blog.csdn.net/newchenxf/article/details/51750239

         这个方案,反正我是没搞定,坑大发了,一会少这个库一会少那个库,等都补齐了又报各种引用找不到的链接错误。这也难怪,C语言没有类似maven/gradle之类的包管理工具,导致版本依赖非常麻烦

       3.使用一个固定的docker容器来执行hook,这个方法我觉得可行,需要等老大决策

       4.放弃当前的git2go库,使用纯go的库 go-git。   应该可行,但有一定改动工作量,也需要老大决策

       5.使用纯c开发hook,静态编译libgit2。   这个肯定可行,而且效率高,但纯c开发太。。。。但总之为了性能,只能选用c和go,其他语言就暂别考虑了

        

    展开全文
  • CGOCGO可以让golang和c互相调用,譬如x264或者aac编解码,用go再实现一遍比较麻烦,直接调用c的函数会更合适。CGO可以直接用C的代码,或者C的静态,或者动态,当然C++也是可以的。在import “C”之前加preamble...

    CGO

    CGO可以让golang和c互相调用,譬如x264或者aac编解码,用go再实现一遍比较麻烦,直接调用c的函数会更合适。

    CGO可以直接用C的代码,或者C的静态库,或者动态库,当然C++也是可以的。

    在import “C”之前加preamble(注释),包含头文件。这样在C这个命名空间中就可以用C的函数了。

    这个C包,实际上是个伪包,导入后会解析前面的preamble,用到头文件定义的类型、变量和函数。

    preamble中可以有include,代码,宏定义,编译条件;静态变量不可用,静态函数可用。

    编译条件是用#cgo指定的,包括CFLAGS、CPPFLAGS、CXXFLAGS、LDFLAGS。

    cgo指令还可以用一些变量,譬如${SRCDIR}用来链接静态库。

    下面是个C++导出的库:

    // winlin.h

    #ifdef __cplusplus

    extern "C"{

    #endif

    // get the version.

    extern int winlin_version();

    #ifdef __cplusplus

    }

    #endif

    // winlin.cpp

    // g++ -c -o winlin.o winlin.cpp && ar -rs winlin.a winlin.o

    #include "winlin.h"

    int winlin_version() {

    return 0x01020304;

    }

    // main.cpp

    // g++ -o cpp main.cpp winlin.a

    #include

    #include "winlin.h"

    int main(int argc, char** argv) {

    printf("version is %#x\n", winlin_version());

    return 0;

    }

    下面是main.cpp在Centos6的执行结果:

    [winlin@centos6 gos]$ ./cpp

    version is 0x1020304

    [winlin@centos6 gos]$ ldd cpp

    linux-vdso.so.1 => (0x00007fff9f674000)

    libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003cbda00000)

    libm.so.6 => /lib64/libm.so.6 (0x0000003cb0a00000)

    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003cbca00000)

    libc.so.6 => /lib64/libc.so.6 (0x0000003cb0e00000)

    /lib64/ld-linux-x86-64.so.2 (0x0000003cb0600000)

    cgo,可以在golang中用这个静态库:

    // go run main.go

    package main

    // #include "winlin.h"

    // #cgo LDFLAGS: ${SRCDIR}/winlin.a -lstdc++

    import "C"

    import "fmt"

    func main() {

    fmt.Println("version is", C.winlin_version())

    }

    注意,得在h头文件中,使用c的方式导出符号。

    除此之外,使用c++的库,得在LDFLAGS中加入-lstdc++。

    总之,cgo的编译和一般的c或c++差别不大,引入的库和头文件之类。

    运行结果如下:

    [winlin@centos6 gos]$ go build -o test main.go

    [winlin@centos6 gos]$ ldd test

    linux-vdso.so.1 => (0x00007fff8df9f000)

    libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003cbda00000)

    libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003cb1600000)

    libc.so.6 => /lib64/libc.so.6 (0x0000003cb0e00000)

    libm.so.6 => /lib64/libm.so.6 (0x0000003cb0a00000)

    /lib64/ld-linux-x86-64.so.2 (0x0000003cb0600000)

    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003cbca00000)

    [winlin@centos6 gos]$ ./test

    version is 16909060

    注意:preabmle可以是//,或者是//,但是不能是//,不能多个,会解析失败。

    在Centos6下面的golang程序,没有用cgo:

    [winlin@centos6 srs-plus]$ ldd objs/bocar

    linux-vdso.so.1 => (0x00007fffb1fff000)

    libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003cb1600000)

    libc.so.6 => /lib64/libc.so.6 (0x0000003cb0e00000)

    /lib64/ld-linux-x86-64.so.2 (0x0000003cb0600000)

    下面是用了cgo的golang程序:

    [winlin@centos6 gos]$ ldd test

    linux-vdso.so.1 => (0x00007ffff43ff000)

    libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003cb1600000)

    libc.so.6 => /lib64/libc.so.6 (0x0000003cb0e00000)

    /lib64/ld-linux-x86-64.so.2 (0x0000003cb0600000)

    下面是C++程序:

    [winlin@centos6 srs-plus]$ ldd objs/srs

    linux-vdso.so.1 => (0x00007fff5d9ff000)

    libdl.so.2 => /lib64/libdl.so.2 (0x0000003cb1200000)

    libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003cbda00000)

    libm.so.6 => /lib64/libm.so.6 (0x0000003cb0a00000)

    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003cbca00000)

    libc.so.6 => /lib64/libc.so.6 (0x0000003cb0e00000)

    /lib64/ld-linux-x86-64.so.2 (0x0000003cb0600000)

    都只是引用了系统的so,譬如c和c++,pthread还有ldl之类的。

    展开全文
  • 我是通过golang调用c库,版本是 1.12.5,主要使用upsert接口,并发写入,高并发时达到上千,但发现运行一段时间后,就会core掉,信息如附件1.png所示, [img=...
  • 如果不设置环境变量,会导致函数未声明、未定义的引用 等问题 解决办法: export CGO_CFLAGS='-Ixxxx' export CGO_LDFLAGS='-Lxxxx -lxxxx'

    如果不设置环境变量,会导致函数未声明、未定义的引用 等问题

    解决办法:

    export CGO_CFLAGS='-Ixxxx'

    export CGO_LDFLAGS='-Lxxxx -lxxxx'

    展开全文
  • Cgo 使得Go程序能够调用C代码. cgo读入一个用特别的格式写的Go语言源文件, 输出Go和C程序, 使得C程序能打包到Go语言的程序包中.举例说明一下. 下面是一个Go语言包, 包含了两个函数 -- Random 和 Seed -- 是C语言库中...

    Cgo 使得Go程序能够调用C代码. cgo读入一个用特别的格式写的Go语言源文件, 输出Go和C程序, 使得C程序能打包到Go语言的程序包中.

    举例说明一下. 下面是一个Go语言包, 包含了两个函数 -- Random 和 Seed -- 是C语言库中random和srandom函数的马甲.

    packagerand/*

    #include

    */import"C"funcRandom()int{returnint(C.random())}funcSeed(iint){C.srandom(C.uint(i))}

    我们来看一下这里都有什么内容. 开始是一个包的导入语句.

    rand包导入了"C"包, 但你会发现在Go的标准库里没有这个包. 那是因为C是一个"伪包", 一个为cgo引入的特殊的包名, 它是C命名空间的一个引用.

    rand 包包含4个到C包的引用: 调用 C.random和C.srandom, 类型转换 C.uint(i)还有引用语句.

    Random函数调用libc中的random函数, 然后回返结果. 在C中, random返回一个C类型的长整形值, cgo把它轮换为C.long. 这个值必需转换成Go的类型, 才能在Go程序中使用. 使用一个常见的Go类型转换:

    funcRandom()int{returnint(C.random())}

    这是一个等价的函数, 使用了一个临时变量来进行类型转换:

    funcRandom()int{varr C.long=C.random()returnint(r)}

    Seed函数则相反. 它接受一个Go语言的int类型, 转换成C语言的unsigned int类型, 然后传递给C的srandom函数.

    funcSeed(iint){C.srandom(C.uint(i))}

    需要注意的是, cgo中的unsigned int类型写为C.uint; cgo的文档中有完整的类型列表.

    这个例子中还有一个细节我们没有说到, 那就是导入语句上面的注释.

    /*

    #include

    */import"C"

    Cgo可以识别这个注释, 并在编译C语言程序的时候将它当作一个头文件来处理. 在这个例子中, 它只是一个include语句, 然而其实它可以是使用有效的C语言代码. 这个注释必需紧靠在import "C"这个语句的上面, 不能有空行, 就像是文档注释一样.

    Strings and things

    与Go语言不同, C语言中没有显式的字符串类型. 字符串在C语言中是一个以0结尾的字符数组.

    Go和C语言中的字符串转换是通过C.CString, C.GoString,和C.GoStringN这些函数进行的. 这些转换将得到字符串类型的一个副本.

    下一个例子是实现一个Print函数, 它使用C标准库中的fputs函数把一个字符串写到标准输出上:

    packageprint// #include // #include import"C"import"unsafe"funcPrint(sstring){cs:=C.CString(s)C.fputs(cs,(*C.FILE)(C.stdout))C.free(unsafe.Pointer(cs))}

    在C程序中进行的内存分配是不能被Go语言的内存管理器感知的. 当你使用C.CString创建一个C字符串时(或者其它类型的C语言内存分配), 你必需记得在使用完后用C.free来释放它.

    调用C.CString将返回一个指向字符数组开始处的指错, 所以在函数退出前我们把它转换成一个unsafe.Pointer(Go中与C的void 等价的东西), 使用C.free来释放分配的内存. 一个惯用法是在分配内存后紧跟一个defer(特别是当这段代码比较复杂的时候), 这样我们就有了下面这个Print函数:

    funcPrint(sstring){cs:=C.CString(s)defer C.free(unsafe.Pointer(cs))C.fputs(cs,(*C.FILE)(C.stdout))}

    构建 cgo 包

    如果你使用goinstall, 构建cgo包就比较容易了, 只要调用像平常一样使用goinstall命令, 它就能自动识别这个特殊的import "C", 然后自动使用cgo来编译这些文件.

    如果你想使用Go的Makefiles来构建, 那在CGOFILES变量中列出那些要用cgo处理的文件, 就像GOFILES变量包含一般的Go源文件一样.

    rand包的Makefile可以写成下面这样:

    include $(GOROOT)/src/Make.inc

    TARG=goblog/rand

    CGOFILES=\rand.go\include $(GOROOT)/src/Make.pkg

    然后输入gomake开始构建.

    更多 cgo 的资源

    cgo的文档中包含了关于C伪包的更多详细的说明, 以及构建过程. Go代码树中的cgo的例子给出了更多更高级的用法.

    一个简单而又符合Go惯用法的基于cgo的包是Russ Cox写的gosqlite. 而Go语言的网站上也列出了更多的的cgo包.

    最后, 如果你对于cgo的内部是怎么运作这个事情感到好奇的话, 去看看运行时包的cgocall.c文件的注释吧.

    展开全文
  • cgo 提供了 golangC 语言相互调用的机制。几乎所有的编程语言都有C语言的影子,当然golang也不例外。可以看到golang的创始者们与C语言有着密切的联系。下面我们将通过快速入门小例子来掌握cgo的基本用法。 最简...
  • golang 调用C语言 Cgo

    2013-03-30 10:34:00
    下面是一个Go语言包, 包含了两个函数 -- Random 和 Seed -- 是C语言库中random和srandom函数的马甲.   package rand   /*  #include  */ import "C" func Random () int { return int ( C...
  • Golang调用CUDA

    2016-03-02 21:47:32
    c, d_c, size, cudaMemcpyDeviceToHost); // Cleanup cudaFree(d_a); cudaFree(d_b); cudaFree(d_c); return 0; } </code></pre> <p>test.go: <pre><code>package main import "fmt" //#cgo CFLAGS: -I. //#...
  • golang调用动态

    千次阅读 2015-06-16 09:57:55
    测试动态 test_so.h int test_so_func(int a,int b);   test_so.c #include "test_so.h" int test_so_func(int a,int b) { return a*b; } 生成so gcc -shared ./test_so.c -o test_so.so ...
  • GolangC的关系非常密切,下面主要介绍在Golang中使用CGolang中嵌入C代码 package main //#include <stdio.h> //#include <stdlib.h> /* 6 void Hello(char *str) { 7 printf("%s\n",str); 8 } ...
  • golang调用c文件

    千次阅读 2018-06-08 17:33:54
    c语言的头文件foo.h int count; void foo(); c语言的实现文件foo.c #include &lt;stdio.h&gt; #include "foo.h"...golang调用c语言 package main // #include &l...
  • golang 调用C,C++

    2020-09-27 18:05:51
    前言:Golang调用是通过cgo完成的,Golang调用C++,则需要将C++函数导出包装为C函数,然后再通过cgo完成调用,话不多说,直接给出调用示例。 开发工具:Clion,Goland 首先msys2,通过msys2安装mingw,cmake等开发C...
  • 1.golang生成c-shared类型到so 建立文件夹hello,创建main.go文件,内容如下: package main import "C" func main() {} //export Hello func Hello() string { return "Hello" } //export Test func Test()...
  • 1、golang链接c静态的方法可以见这个示例: https://github.com/atercattus/go-static-link-example https://github.com/shadowmint/go-static-linking https://github.com/AlekSi/cgo-by-example (这个示例我...
  • 本篇文章主要介绍golang调用c实现的dll时,具体的一些方式。比如值传递、参数传递、指针等等的一些使用。 一、dll的代码 c实现的dll代码: hello.h #ifndef _HELLO_H_ #define _HELLO_H_ #include &lt;stdio.h...
  • 最近使用golang调用c++的dll文件,简单了解了一下,特作此笔记:一、DLL 的编制与具体的编程语言及编译器无关dll分com的dll和动态dll,Com组件dll:不管是何种语言写的都可以调用,但com分很多种。比如而php只能调用...
  • 本篇文章主要介绍golang调用c实现的.so时,具体的一些方式。比如值传递、参数传递、指针等等的一些使用,使用的是cgo来调用。 一、动态的实现 hello.h #ifndef _CALL_H_ #define _CALL_H_ void hello(char *...
  • golang调用C程序传递和返回字符串

    千次阅读 2018-09-15 15:06:32
    项目中需要用Golang调用C生成密码,因此借机熟悉了一下cgo的一些用法。 基本用法网上已经有教程,但是关于字符串的传递的文章还不多,因此记录下。 1. 编写C文件,包含一个函数,函数接受字符串,同时返回字符数组...
  • bin文件可以是C++生成,或其他语言生成,此处用的是C++生成的二进制文件 如果你想在go语言中通过读取文件,...1:功能:需要用go调用第三方bin文件,传参进去,通过读写文件实现进程间的通信。 func (this *Baidu...
  • 生命不止,继续 go go go !...所有,golangc语言的相互调用也是理所应当。什么场合会使用Go与C的互操作呢? 下面的地址给出这样的答案:http://tonybai.com/2012/09/26/interoperability-between-go-a
  • 1. 编译golang 静态package mainimport ("C""fmt")//export Foofunc Foo(a, b int) int {return a + b}//export Barfunc Bar() {fmt.Println("Hello, I'm LiLei.")}func main() {}使用命令编译得到静态和头文件...
  • Golang类似于C的静态语言,效率也接近于C,如果Golang也可以导出可供C调用,那可以和很多高级语言say goodbye了,goodbye似乎又有点武断,但至少说,Golang可以做很多事,而且效率优于很多高级语言,这样说应该...
  • golang调用python实战

    2020-08-21 15:22:05
    所以,直接通过Golang调用libpython,就可以实现Go调Python的功能了。但是过程比较复杂,而go-python提供了针对CPython-2的C-API提供了native-binding能力,方便实现了Go到Python的调用。 但是目前,go-python只支持...
  • Cgo 使得Go程序能够调用C代码. cgo读入一个用特别的格式写的Go语言源文件, 输出Go和C程序, 使得C程序能打包到Go语言的程序包中.举例说明一下. 下面是一个Go语言包, 包含了两个函数 -- Random 和 Seed -- 是C语言库中...
  • Golang调用Python

    2017-07-05 13:57:38
    Python是时髦的机器学习御用开发语言,Golang是大红大紫的新时代后端开发语言。Python很适合让搞算法的写写模型,而Golang很适合提供API服务,两位同志都红的发...所以,直接通过Golang调用libpython,就可以实现Go...
  • GoLang 调用 .so 文件

    千次阅读 2020-07-15 20:32:35
    Go 1.8 提供了一个创建共享的新工具:Plugins!只能在 Linux 和 MacOS 下使用。其可以应用如下场景: ...以下记录一个Golang调用 .so 文件实现动态化编程的小例子: 首先创建一个 go文件 aplugin.go: .

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,047
精华内容 3,618
关键字:

golang调用c库