环境:

  centos_7_x86_x64,gcc_4.8.5

一、安装swig

   1. 安装pcre

yum install -y pcre pcre-tools pcre-devel

   2. 安装yacc

yum install -y byacc

   3. 下载swig-rel-3.0.12.tar.gz

   4. 解压到任意目录下,并生成configure文件

tar -xvzf swig-rel-3.0..tar.gz
cd swig-rel-3.0.
./autogen.sh

   5. 生成Makefile文件

./configure

   6. 编译和安装

make && make install

   7. 验证安装是否成功  

swig -version

  这里说一下为什么要编译swig源码来进行安装,在yum上安装swig的版本比较低,而较低版本的swig不支持-cgo参数,具体见官方文档。

二、安装golang

  1. 安装go

yum install -y go

  2. 验证安装是否成功

go version

三、创建C++动态链接库

  1. 编写test_cpp.h文件

#ifndef _TEST_CPP_H_
#define _TEST_CPP_H_ #include <stdint.h>
#include <string> /// 回调类
class ICallback {
public:
virtual void notify(const std::string& s) = ;
}; /// 测试类
class TestCall {
public:
static TestCall* Create() { return new TestCall(); } void SetCallback(ICallback* callback) { callback_ = callback; } int32_t Test(const std::string& s); private:
TestCall() : callback_(NULL) {} ICallback* callback_;
}; #endif

  2. 编写test_cpp.cpp文件

#include <iostream>
#include "test_cpp.h" int32_t TestCall::Test(const std::string & s) {
std::cout << "TestCall::Test(" << s << ")" << std::endl;
if (callback_) {
callback_->notify(s);
}
return ;
}

  3. 编写CMakeLists.txt文件

cmake_minimum_required(VERSION 2.8)

project(test_cpp C CXX)

set(SRC_LISTS test_cpp.cpp)
add_library(test_cpp SHARED ${SRC_LISTS})

  4. 编译生成动态链接库libtest_cpp.so

mkdir cmake
cd cmake
cmake ..
make

  由于在golang中不能直接使用C++函数,所以我们稍后会使用swig工具,生成C函数提供给golang使用。

四、使用swig从C++生成C函数接口

  1. 编写定义文件go_test_cpp.swigcxx

/* Copyright 2011 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. */ /* An example of writing a C++ virtual function in Go. */ %module(directors="") go_test_cpp %init %{
//printf("Initialization rms done.\n");
%} %typemap(gotype) (char **ppInstrumentID, int nCount) "[]string" %typemap(in) (char **ppInstrumentID, int nCount)
%{
{
int i;
_gostring_* a; $ = $input.len;
a = (_gostring_*) $input.array;
$ = (char **) malloc (($ + ) * sizeof (char *));
for (i = ; i < $; i++) { /* Not work */
//_gostring_ *ps = &a[i];
//$1[i] = (char *) ps->p;
//$1[i][ps->n] = '\0'; /*Work well*/
_gostring_ *ps = &a[i];
$[i] = (char*) malloc(ps->n + );
memcpy($[i], ps->p, ps->n);
$[i][ps->n] = '\0';
}
$[i] = NULL;
}
%} %typemap(argout) (char **ppInstrumentID, int nCount) "" /* override char *[] default */ %typemap(freearg) (char **ppInstrumentID, int nCount)
%{
{
int i;
for (i = ; i < $; i++)
{
free ($[i]);
}
free($);
}
%} /* 在复杂的企业环境中,可能有一些 C/C++ 头文件定义了您希望向脚本框架公开的全局变量和常量。
* 在接口文件中使用 %include <header.h> 和 %{ #include <header.h> %},可解决在头文件中重复所有元素的声明的问题。
*/ /* Includes the header files in the wrapper code */
%header %{
#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) || defined(WIN32) #include "test_cpp.h" #else #include "test_cpp.h" #endif
%} /* Parse the header files to generate wrappers */
%include "std_string.i" %feature("director") ICallback; #if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) || defined(WIN32) %include "./../cpp/test_cpp.h" #else %include "./../cpp/test_cpp.h" #endif

  有几个点我们需要注意:

    1.1 指定生成go源文件中的包名
%module(directors="") go_test_cpp
    1.2 指定生成C++源文件中的include代码
%header %{
#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) || defined(WIN32) #include "test_cpp.h" #else #include "test_cpp.h" #endif
%}
    1.3 可以让go支持继承某个C++类
%feature("director") ICallback;
    1.4 指定需要解析C++头文件,生成go和C++的包装代码
#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) || defined(WIN32)

%include "./../cpp/test_cpp.h"

#else

%include "./../cpp/test_cpp.h"

#endif

  2. 生成go源文件和C++源文件

swig -go -cgo -intgosize  -c++ ./go_test_cpp.swigcxx

  总共生成了3个文件:go_test_cpp.go、go_test_cpp_wrap.h和go_test_cpp_wrap.cxx

  3. 在该目录下编写CMakeLists.txt文件

cmake_minimum_required(VERSION 2.8)

project(go_test_cpp C CXX)

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../cpp)
set(SRC_LISTS go_test_cpp_wrap.cxx)
add_library(go_test_cpp STATIC ${SRC_LISTS})

  4. 编译生成静态库libgo_test_cpp.a

mkdir cmake
cd cmake
cmake ..
make

  最后编译的静态库是给go使用的,大致调用流程是:go  <=>  libgo_test_cpp.a  <=>  libtest_cpp.so

四、在go中使用C函数接口

  1. 将go_test_cpp.go文件拷贝到go工程目录下的go_test_cpp目录下

  2. 编写libgo_test_cpp.go文件

// Copyright 2012 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. package go_test_cpp //#cgo linux LDFLAGS: -fPIC -L${SRCDIR}/../../cpp/cmake -L${SRCDIR}/../../swig/cmake -Wl,-rpath=${SRCDIR}/../../cpp/cmake -ltest_cpp -lgo_test_cpp -lstdc++
//#cgo linux CPPFLAGS: -fPIC -I.
import "C"

  链接libtest_cpp.so和libgo_test_cpp.a模块;应该将libgo_test_cpp.go文件保存在go_test_cpp目录下,它和go_test_cpp.go都属于同一个包。

  3. 编写main.go文件调用C函数

package main

import(
"fmt"
"unsafe"
"time"
"./go_test_cpp"
) type my_callback struct {
go_test_cpp.ICallback
} func (this my_callback) Notify(arg2 string) {
fmt.Printf("c++ Notify:%s\n", arg2)
} func main() { cb := go_test_cpp.NewDirectorICallback(my_callback{}) test := go_test_cpp.TestCallCreate()
test.SetCallback(cb) res_ptr := test.Test("Hello World!").Swigcptr()
res := *(*int32)(unsafe.Pointer(res_ptr))
if res == 0 {
fmt.Println("Test success!")
} else {
fmt.Println("init failed[", res, "]!")
}
go_test_cpp.Swig_free(res_ptr) time.Sleep(time.Second*1)
fmt.Println("end")
}

  4. 运行main.go

  

go run main.go

资源下载链接: http://pan.baidu.com/s/1jIA5mXS 密码: ksnq

使用swig工具为go语言与c++进行交互的更多相关文章

  1. 采用 PAT工具及CSP语言,对一个问题进行自动机 建模

    pat是新加坡国立开发的工具,需要的去官网下http://www.comp.nus.edu.sg/~pat/ ,学了一天,是个不错的自动机验证工具,感觉还不错啊. 验证一个数是否为斐波那契数且为质数 ...

  2. 求推荐go语言开发工具及go语言应该以哪种目录结构组织代码?

    go语言的开发工具推荐? go语言开发普通程序及开发web程序的时候,应该以哪种目录结构组织代码? 求推荐go语言开发工具及go语言应该以哪种目录结构组织代码? >> golang这个答案 ...

  3. (转)python中调用R语言通过rpy2 进行交互安装配置详解

    python中调用R语言通过rpy2 进行交互安装配置详解(R_USER.R_HOME配置) 2018年11月08日 10:00:11 luqin_ 阅读数:753   python中调用R语言通过r ...

  4. 用任意语言与WebService进行交互

    using System; using System.Web.Services; using YY.SmsPlatform.Common.Objects; using YY.SmsPlatform.C ...

  5. C语言实现的文件交互

    计算机与外部设备的交互依靠文件完成 文件是记录在外部介质上的数据的集合:例如1.c 是源码 1.exe可执行的文件 文件的分类 按组织结构: 记录文件:有一定结构的文件,可以解析成字段值的文件: 流式 ...

  6. Demo Swig

    演示使用swig工具创建c语言的java接口,生成.so库和java接口文件. 在此之前先要安装swig,安装方法:sudo apt-get install swig 1.使用eclipse创建工程. ...

  7. SWIG 多语言接口变换 【转】

    一.             SWIG 是Simple Wrapper and Interface Generator的缩写,是一个帮助使用C或者C++编写的软件创建其他编语言的API的工具.例如,我 ...

  8. go语言,golang学习笔记1 官网下载安装,中文社区,开发工具LiteIDE

    go语言,golang学习笔记1 官网下载安装,中文社区,开发工具LiteIDE Go语言是谷歌2009发布的专门针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美C或C++代码的速 ...

  9. 初识代码封装工具SWIG(回调Python函数)

    这不是我最早使用swig了,之前在写Kynetix的时候就使用了swig为python封装了C语言写的扩展模块.但是当时我对C++还不是很了解,对其中的一些概念也只是拿来直接用,没有理解到底是什么,为 ...

随机推荐

  1. 剑指offer 05:用两个栈实现队列

    题目描述 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 解题代码 import java.util.Stack; public class Solution{ ...

  2. Java集合框架源码分析(2)LinkedList

    链表(LinkedList) 数组(array)和数组列表(ArrayList)都有一个重大的缺陷: 从数组的中间位置删除一个元素要付出很大的代价,因为数组中在被删除元素之后的所有元素都要向数组的前端 ...

  3. java线程自带队列的使用以及线程阻塞

    java线程,设置队列的大小实现队列阻塞 public class QueueThreads { private static int nThreads = 4;//Runtime.getRuntim ...

  4. vue中修改了数据但视图无法更新的情况

    数组数据变动:我们使用某些方法操作数组,变动数据时,有些方法无法被vue监测,有些可以 Vue包装了数个数组操作函数,使用这些方法操作的数组去,其数据变动时会被vue监测: push() pop() ...

  5. Java线程池ThreadPoolExecutor&&Executors

    一.先看看传统的开启线程. new Thread(new Runnable() { @Override public void run() { } }).start(); 缺点: 1.每次new Th ...

  6. python安装scrapy

    Scrapy基于事件驱动网络框架 Twisted 编写,Twisted是一个异步非阻塞框架. 安装 scrapy 要先安装 Twisted,不然无法安装成功,链接: Python Extension ...

  7. PFM 图片格式

    PFM  图片格式 参考:   https://linux.die.net/man/5/pfm 1. 描述 本文档描述了Netpbm转换器pamtopfm(1)和pfmtopam(1)所理解的PFM图 ...

  8. Jsp 国际化访问首页选择展示不同字体小例子

    要求:创建一个首页,默然显示英文信息,但可以让用户选择使用英文,繁体中文或简体中文. 1.编写hello_en_US.txt,内容如下: cc.openhome.welcome=welcomecc.o ...

  9. mybatis源码解析之环境准备

    概述 对于mybatis而言,大家一定都不陌生,我相信很多同学都跟我一样,用起来非常的熟练,但是其内部的实现原理呢,不太清楚,经常面试的时候,面试官问及这方面的知识,都只能尴尬的回答不知道,或者不清楚 ...

  10. 自动化测试badboy脚本开发(一)

    badboy的检查点: 检查点设置例子:以上一节脚本录制方法简单录制搜索“badboy”脚本,在搜索框中选中搜索内容(注意录制脚本后要停止录制)→点击工具栏中的Tools→选择Add Assertio ...