此例子来自于go源码中,借此来和大家分享一下两者如何调用,网上很多文章语言不详,也没有一个完整的测试例子

  1. 目录结构

首先src 目录下有

testcgowin目录下:

这里的_obj目录是cgo生成的

这里需要展示的是go中如何调用c语言导出函数,以及在c语言中如何调用go的导出函数.

关键是cthread.go和cthread_windows.c两个文件

  1. go文件

cthread.go内容:

package ctestcgowin

// extern void doAdd(int, int);
import "C"

import (
"sync"
"fmt"
)

var sum struct {
sync.Mutex
i int
}

//export Add
func Add(x int) {
defer func() {
recover()
}()
sum.Lock()
sum.i += x
sum.Unlock()
var p *int
*p = 2
}

func TestCthread() {
sum.i = 0
C.doAdd(10, 6)

want := 10 * (10 - 1) / 2 * 6
if sum.i != want {
fmt.Printf("sum=%d, want %d\n", sum.i, want)
}
fmt.Println("want=",want)
}

这里的:

// extern void doAdd(int, int);
import "C"

这两行非常关键,必须紧挨着,不能有空行,而且要紧跟着package语句,import要单独写

这里的注释相当于c语言声明了一个函数,你用#include当然也可以。遵循的都是c的语法,少个分号都是会报错的。

然后是下面两行:

//export Add
func Add(x int) {

export Add表示这是go要导出的一个函数,这样c里面可以调用。

如果此行注释删掉,c文件将会提示找不到Add函数。

cthread_windows.c:18: undefined reference to `Add'

  1. c语言文件

// Copyright 2013 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <process.h>
#include "_cgo_export.h" __stdcall
static unsigned int
addThread(void *p)
{
int i, max; max = *(int*)p;
for(i=0; i<max; i++)
Add(i);
return 0;
} void
doAdd(int max, int nthread)
{
enum { MaxThread = 20 };
int i;
uintptr_t thread_id[MaxThread]; if(nthread > MaxThread)
nthread = MaxThread;
for(i=0; i<nthread; i++)
thread_id[i] = _beginthreadex(0, 0, addThread, &max, 0, 0);
for(i=0; i<nthread; i++) {
WaitForSingleObject((HANDLE)thread_id[i], INFINITE);
CloseHandle((HANDLE)thread_id[i]);
}
}

 

我不晓得这个宏WIN32_LEAN_AND_MEAN什么意思,跟着写就行了,也没有去查阅文档以及代码。

这里doAdd是导出函数,addThread不需要导出,所以加了static,

#include "_cgo_export.h"是因为我们需要调用go的导出函数Add,有兴趣的可以看看_obj目录

到此为止,相互之间的关系已经说明白了,当然go与c语言之间的类型转换,留作以后再说。

  1. 编译生成.a文件

接下来如果想要利用这个lib,很简单,

运行cgo生成必要的文件,然后go install将编译生成testcgowin.a文件,此文件在pkg\windows_386目录下

  1. 利用.a文件

直接看testcgowin.go文件内容即可:

package main
import "testcgowin" func main(){
ctestcgowin.TestCthread();
}

 

  1. 结语

c和go互相调用的关键都是通过注释实现的,并且cgo会自己编译相应的.c文件,不需要特别说明,只需要放到相应目录下即可。

总的来说go为了和c互操作做了很多,虽然没法像c++那么方便,但是基本上来收还是很顺利的。

go与c互相调用的更多相关文章

  1. 黑马毕向东Java基础知识总结

    Java基础知识总结(超级经典) 转自:百度文库 黑马毕向东JAVA基础总结笔记    侵删! 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部 ...

  2. 《果壳中的C# C# 5.0 权威指南》 - 学习笔记

    <果壳中的C# C# 5.0 权威指南> ========== ========== ==========[作者] (美) Joseph Albahari (美) Ben Albahari ...

  3. JS调用Android、Ios原生控件

    在上一篇博客中已经和大家聊了,关于JS与Android.Ios原生控件之间相互通信的详细代码实现,今天我们一起聊一下JS调用Android.Ios通信的相同点和不同点,以便帮助我们在进行混合式开发时, ...

  4. 【原创分享·支付宝支付】HBuilder打包APP调用支付宝客户端支付

    前言 最近有点空余时间,所以,就研究了一下APP支付.前面很早就搞完APP的微信支付了,但是由于时间上和应用上的情况,支付宝一直没空去研究.然后等我空了的时候,发现支付宝居然升级了支付逻辑,虽然目前还 ...

  5. 操作系统篇-调用门与特权级(CPL、DPL和RPL)

    || 版权声明:本文为博主原创文章,未经博主允许不得转载. 一.前言 在前两篇文章(<操作系统篇-浅谈实模式与保护模式>和<操作系统篇-分段机制与GDT|LDT>)中,我们提到 ...

  6. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  7. django server之间通过remote user 相互调用

    首先,场景是这样的:存在两个django web应用,并且两个应用存在一定的联系.某些情况下彼此需要获取对方的数据. 但是我们的应用肯经都会有对应的鉴权机制.不会让人家随随便便就访问的对吧.好比上车要 ...

  8. 调用AJAX做登陆和注册

    先建立一个页面来检测一下我们建立的用户名能不能用,看一下有没有已经存在的用户名吗 可以通过ajax提示一下 $("#uid").blur(function(){ //取用户名 va ...

  9. nodejs进阶(2)—函数模块调用

    函数调用 1. 文件内普通函数调用 创建一个js文件命名为2_callFunction.js,其中定义一个函数fun1,向返回对象输出了一段字符串“你好,我是fun1”. //------------ ...

  10. 【初学python】使用python调用monkey测试

    目前公司主要开发安卓平台的APP,平时测试经常需要使用monkey测试,所以尝试了下用python调用monkey,代码如下: import os apk = {'j': 'com.***.test1 ...

随机推荐

  1. 让memcached分布式

    memcached是应用最广的开源cache产品,它本身不提供分布式的解决方案,我猜想一方面它想尽量保持产品简单高效,另一方面cache的key-value的特性使得让memcached分布式起来比较 ...

  2. Annotation之一:Java Annotation基本功能介绍

    一.元数据的作用 如果要对于元数据的作用进行分类,目前还没有明确的定义,不过我们可以根据它所起的作用,大致可分为三类: 编写文档:通过代码里标识的元数据生成文档.这是最常见的,也是java 最早提供的 ...

  3. 1097 Deduplication on a Linked List

    题意: 给出一个链表,删除绝对值相同的结点,对于每个绝对值为K的结点,只保留第一次出现的那个.把被移除的结点组成一个新链表,输出删除去重后的链表和新链表. 思路:考察链表的“删除”操作,不难. 代码: ...

  4. python开发mysql:mysql安装(windows)&密码找回&存储引擎简介&库表的增删改查

    一,mysql安装 下载地址 https://dev.mysql.com/downloads/file/?id=471342 解压后,将目录C:\mysql-5.7.19-winx64\bin添加到计 ...

  5. 实验吧CTF题库-隐写术(部分)

    Spamcarver 用kali下载图片 root@sch01ar:~# wget http://ctf5.shiyanbar.com/stega/spamcarver/spamcarver.jpg ...

  6. windows右键打开方式里面添加新的应用程序

    1.打开注册表编辑器.打开运行窗口,快捷键,开始+R.输入“regedit”,回车确定. 2.进入注册表编辑器的HKEY_CLASSES_ROOT文件夹下的*子文件夹下的shell文件夹. 3.右键s ...

  7. python数据字典的操作

    一.什么是字典? 字典是Python语言中唯一的映射类型. 映射类型对象里哈希值(键,key)和指向的对象(值,value)是一对多的的关系,通常被认为是可变的哈希表. 字典对象是可变的,它是一个容器 ...

  8. SSH免密登陆配置过程和原理解析

    SSH免密登陆配置过程和原理解析 SSH免密登陆配置过很多次,但是对它的认识只限于配置,对它认证的过程和基本的原理并没有什么认识,最近又看了一下,这里对学习的结果进行记录. 提纲: 1.SSH免密登陆 ...

  9. libevent源码深度剖析三

    libevent源码深度剖析三 ——libevent基本使用场景和事件流程 张亮 1 前言 学习源代码该从哪里入手?我觉得从程序的基本使用场景和代码的整体处理流程入手是个不错的方法,至少从个人的经验上 ...

  10. php 扩展开发

    Linux下用C开发PHP扩展 一.首先下载PHP源码包,假设源码包目录为:/software/php-5.2.13 #> cd /software/php-5.2.13/ext 二.假设我们要 ...