http://tonybai.com/2012/09/26/interoperability-between-go-and-c/

// foo.h

int count;
void foo(); //foo.c
#include "foo.h" int count = ;
void foo() {
printf("I am foo!\n");
}
//foo.go

package main

// #cgo LDFLAGS: -L ./ -lfoo
// #include <stdio.h>
// #include <stdlib.h>
// #include "foo.h"
import "C"
import "fmt“ func main() {
fmt.Println(C.count)
C.foo()
}
使用静态库
$> gcc -c foo.c
$> ar rv libfoo.a foo.o
[diego@localhost ~/GoWork/src/applycation/testCgo]# go build foo.go
[diego@localhost ~/GoWork/src/applycation/testCgo]# ./foo I am foo!
[diego@localhost ~/GoWork/src/applycation/testCgo]# gcc -fPIC -shared -o libfoo.so foo.c
[diego@localhost ~/GoWork/src/applycation/testCgo]# rm li
libfoo.a libfoo.so*
[diego@localhost ~/GoWork/src/applycation/testCgo]# rm libfoo.a
[diego@localhost ~/GoWork/src/applycation/testCgo]# go build fo
foo* foo.c foo.go foo.h foo.o
[diego@localhost ~/GoWork/src/applycation/testCgo]# go build foo.
foo.c foo.go foo.h foo.o
[diego@localhost ~/GoWork/src/applycation/testCgo]# go build foo.go
[diego@localhost ~/GoWork/src/applycation/testCgo]# ./foo I am foo!
[diego@localhost ~/GoWork/src/applycation/testCgo]#

http://tonybai.com/2012/09/26/interoperability-between-go-and-c/

与在Go中使用C源码相比,在C中使用Go函数的场合较少。在Go中,可以使用"export + 函数名"来导出Go函数为C所使用,看一个简单例子:
 
package main
 
/*
#include <stdio.h>
 
extern void GoExportedFunc();
 
void bar() {
        printf("I am bar!\n");
        GoExportedFunc();
}
*/
import "C"
 
import "fmt"
 
//export GoExportedFunc
func GoExportedFunc() {
        fmt.Println("I am a GoExportedFunc!")
}
 
func main() {
        C.bar()
}
 
不过当我们编译该Go文件时,我们得到了如下错误信息:
 
# command-line-arguments
/tmp/go-build163255970/command-line-arguments/_obj/bar.cgo2.o: In function `bar':
./bar.go:7: multiple definition of `bar'
/tmp/go-build163255970/command-line-arguments/_obj/_cgo_export.o:/home/tonybai/test/go/bar.go:7: first defined here
collect2: ld returned 1 exit status
 
代码似乎没有任何问题,但就是无法通过编译,总是提示“多重定义”。翻看Cgo的文档,找到了些端倪。原来
 
There is a limitation: if your program uses any //export directives, then the C code in the comment may only include declarations (extern int f();), not definitions (int f() { return 1; }).
 
似乎是// extern int f()与//export f不能放在一个Go源文件中。我们把bar.go拆分成bar1.go和bar2.go两个文件:
 
// bar1.go
 
package main
 
/*
#include <stdio.h>
 
extern void GoExportedFunc();
 
void bar() {
        printf("I am bar!\n");
        GoExportedFunc();
}
*/
import "C"
 
func main() {
        C.bar()
}
 
// bar2.go
 
package main
 
import "C"
import "fmt"
 
//export GoExportedFunc
func GoExportedFunc() {
        fmt.Println("I am a GoExportedFunc!")
}
 
编译执行:
 
$> go build -o bar bar1.go bar2.go
$> bar
I am bar!
I am a GoExportedFunc!
 

Go代码:

func TestCallback() {
    f1 := syscall.NewCallback(PlusOne)
    f2 := syscall.NewCallbackCDecl(PlusTwo)
    var m uint32 = 20
    var n uint32 = 80     // Func1 __stdcall
    fmt.Println(C.Func1(C.uint(m), (*[0]byte)(unsafe.Pointer(f1)))) // 21     // Func2 __cdecl
    fmt.Println(C.Func2(C.uint(n), (*[0]byte)(unsafe.Pointer(f2)))) // 82
} func PlusOne(n uint32) uintptr {
    return uintptr(n + 1)
} func PlusTwo(n uint32) uintptr {
    return uintptr(n + 2)
}

C.Func1的第二个参数类型为函数,所以要传入一个*[0]byte。   http://studygolang.com/articles/2629

http://blog.giorgis.io/cgo-examples

Go与C语言的互操作 cgo的更多相关文章

  1. [转]Go与C语言的互操作

    Go有强烈的C背景,除了语法具有继承性外,其设计者以及其设计目标都与C语言有着千丝万缕的联系.在Go与C语言互操作(Interoperability)方面,Go更是提供了强大的支持.尤其是在Go中使用 ...

  2. Go语言练习:go语言与C语言的交互——cgo

    1.代码 package main import "fmt" /* #include <stdlib.h> #include <stdio.h> void ...

  3. go与c语言的互操作

    https://tonybai.com/2012/09/26/interoperability-between-go-and-c/ https://tonybai.com/2016/02/21/som ...

  4. C语言和go语言之间的交互

    一.go代码中使用C代码 go代码中使用C代码,在go语言的函数块中,以注释的方式写入C代码,然后紧跟import "C" 即可在go代码中使用C函数 代码示例: go代码:tes ...

  5. C语言和go语言之间的交互 - C语言中使用go语言,使用的go语言又使用了c语言

    一.go语言中使用C语言 go代码中使用C代码,在go语言的函数块中,以注释的方式写入C代码,然后紧跟import “C” 即可在go代码中使用C函数 代码示例: go代码:testC.go 1 pa ...

  6. [C++/CLI编程宝典][2]什么是C++/CLI语言

    对于什么是C++/CLI,我们首先能够简单的将其名字划分为两部分来理解,第一,C++,我们熟悉的眼下被广泛使用的面向对象的ISO国际标准的高级语言,也称为ISOC++,我们这里以后均称其为ISOC++ ...

  7. C# 语言规范_版本5.0 (第17章 特性)

    1. 特性 C# 语言的一个重要特征是使程序员能够为程序中定义的实体指定声明性信息.例如,类中方法的可访问性是通过使用 method-modifiers(public.protected.intern ...

  8. C# 语言规范_版本5.0 (第0章 目录)

    C# 语言规范 版本5.0 注意 © 1999-2012 Microsoft Corporation.保留所有权利. Microsoft.Windows.Visual Basic.Visual C# ...

  9. C#6.0语言规范(十七) 特性

    许多C#语言使程序员能够指定有关程序中定义的实体的声明性信息.例如,在一个类中的方法的可访问性由与装饰它指定method_modifier小号public,protected,internal,和pr ...

随机推荐

  1. PyCharm学习笔记(一) 界面配置

     通过Ctrl+鼠标滚轮调整字体大小  设置代码区默认字体及大小 设置调试区的字体大小 设置代码风格:如Tab缩进 定义Python模板文件 # @Time : ${DATE} ${TIME} # @ ...

  2. (转)在Xcode 7上直接使用Clang Address Sanitizer

    原文地址: http://www.cocoachina.com/ios/20150730/12830.html WWDC 2015上,除了Swift 2.0外,还有一个令人激动的消息:可以直接在Xco ...

  3. Idea使用Tomcat乱码 tomcat 9.0 8.5.37乱码

    使用新版tomcat 如8.5.37,9.0.14的时候idea控制台输出乱码,很简单老版本的如8.5.31就不会乱码,使用比较工具比较一下发现如下变化, 关键的关键是\apache-tomcat-8 ...

  4. 学习javascript中的事件——事件流

    事件概念: HTML中与javascript交互是通过事件驱动来实现的,例如鼠标点击事件onclick.页面的滚动事件onscroll等等,可以向文档或者文档中的元素添加事件侦听器来预订事件.想要知道 ...

  5. CI - Set CSRF Hash and Cookie

    /** * Set CSRF Hash and Cookie * * @return string */ protected function _csrf_set_hash() { if ($this ...

  6. Android刷新页面

    代码改变世界 Android刷新页面 继承 extends Activity /*** 调用onCreate(), 目的是刷新数据,  从另一activity界面返回到该activity界面时, 此方 ...

  7. Redis常见配置redis.conf

    redis的配置文件.相信学过SSH或SSM的读者都知道,配置文件的使用在当下开发已十分普遍,希望大家要熟悉习惯这 种开发方式,废话不多说,来开始我们今天的内容吧. 首先得找到 redis 的配置文件 ...

  8. day2之爬取拉勾网

    认证流程 浏览器清空cookies 步骤一 访问拉勾网网站  https://www.lagou.com/ 做了些什么: 以get方式请求"https://www.lagou.com/&qu ...

  9. Fruit Ninja

    Fruit Ninja 时间限制:C/C++ 5秒,其他语言10秒 空间限制:C/C++ 262144K,其他语言524288K 64bit IO Format: %lld 题目描述 Fruit Ni ...

  10. EC++学习笔记(二) 构造/析构/赋值

    条款05:了解c++默默编写并调用了哪些函数 编译器可以暗自为 class 创建default构造函数,copy构造函数,copy assignment操作和析构函数所有这些函数都是 public 并 ...