程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> go與c互相調用,go調用

go與c互相調用,go調用

編輯:關於C語言

go與c互相調用,go調用


此例子來自於go源碼中,借此來和大家分享一下兩者如何調用,網上很多文章語言不詳,也沒有一個完整的測試例子

首先src 目錄下有

testcgowin目錄下:

這裡的_obj目錄是cgo生成的

這裡需要展示的是go中如何調用c語言導出函數,以及在c語言中如何調用go的導出函數.

關鍵是cthread.go和cthread_windows.c兩個文件

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'

// 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語言之間的類型轉換,留作以後再說。

接下來如果想要利用這個lib,很簡單,

運行cgo生成必要的文件,然後go install將編譯生成testcgowin.a文件,此文件在pkg\windows_386目錄下

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

package main
import "testcgowin"


func main(){
ctestcgowin.TestCthread();
}

 

c和go互相調用的關鍵都是通過注釋實現的,並且cgo會自己編譯相應的.c文件,不需要特別說明,只需要放到相應目錄下即可。

總的來說go為了和c互操作做了很多,雖然沒法像c++那麼方便,但是基本上來收還是很順利的。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved