囲碁言語におけるCGOの実践的な使用
部門製品のビジネス関数は、Golangによって開発されたが、いくつかの関数は、これらのように、ネットSNMP、bfdプロトコルなどのC言語で書かれている、あなたが再編集するGO言語を使用する場合、両方の実装の複雑さもかなり長い時間がかかる、良いことは、GO言語は、直接大幅に効率を改善し、削減GOコード内のCライブラリ機能を呼び出すことができるので、CGOメカニズムを提供していますさらに、それはまた非常に強力ですC言語でGO関数の呼び出しをサポートします。
1. GoでのC関数呼び出しの例。
package main
//
// The referenced C header file needs to be declared in a comment, immediately after the comment needs to have import "C", and there should be no space between this line and the comment
//
/*
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void myprint(char* s) {
printf("%s\n", s);
}
*/
import "C"
import (
"fmt"
"unsafe"
)
func main() {
// Strings created with C.CString need to be freed manually.
cs := C.CString("Hello World\n")
C.myprint(cs)
C.free(unsafe.Pointer(cs))
fmt.Println("call C.sleep for 3s")
C.sleep(3)
return
}
実行します。
2. C言語ライブラリ関数のGo言語呼び出し。
hello.c
#include <stdio.h>
void hello()
{
printf("hello world\n");
}
hello.h
#ifndef HELLO_H
#define HELLO_H
void hello(void);
#endif
コンパイルします。
gcc -c hello.c
ar -cru libhello.a hello.o
package main
//Use #cgo to define the library path
/*
#cgo CFLAGS: -I .
#cgo LDFLAGS: -L . -lhello
#include "hello.h"
*/
import "C"
func main() {
C.hello()
}
実行します。
3. Go は C 言語で使用するための関数をエクスポートします。
main.go
package main
//
//#include <stdio.h>
//int add(int a, int b);
//
import "C"
import (
"fmt"
)
// When using export, no other c functions can be defined in the same file, or an error will be reported.
//Use export to export functions to c calls.
//export GoAdd
func GoAdd(a, b int) int {
return a + b
}
func main() {
a := C.add(1, 2)
fmt.Printf("C.add(1,2) return %d\n", a)
}
cfunc.go
package main
//
//int GoAdd(int a, int b);
//
//int add(int a, int b)
//{
// return GoAdd(a, b);
//}
//
import "C"
実行します。
4. Go は、c で使用するための関数ポインタをエクスポートします。
もう一つ使い方があって、こちらの方がよく使います。それは、関数ポインタを渡すことです。GOの関数はアドレス指定ができないので、次の例のように、変換操作をするための中間関数を書く必要があるのです。
clibrary.c
#include <stdio.h>
#include "clibrary.h"
// the argument is a function pointer
void some_c_func(callback_fcn callback)
{
int arg = 2;
printf("C.some_c_func(): calling callback with arg = %d\n", arg);
int response = callback(2);
printf("C.some_c_func(): callback responded with %d\n", response);
}
clibrary.h
#ifndef CLIBRARY_H
#define CLIBRARY_H
//define function pointer
typedef int (*callback_fcn)(int);
void some_c_func(callback_fcn);
#endif
囲碁のコードです。
package main
/*
#cgo CFLAGS: -I .
#cgo LDFLAGS: -L . -lclibrary
#include "clibrary.h"
int callOnMeGo_cgo(int in); // declare
*/
import "C"
import (
"fmt"
"unsafe"
)
//export callOnMeGo
func callOnMeGo(in int) int {
return in + 1
}
func main() {
fmt.Printf("Go.main(): calling C function with callback to us\n")
//use unsafe.Pointer conversion
C.some_c_func((C.callback_fcn)(unsafe.Pointer(C.callOnMeGo_cgo)))
}
中間的な機能。
package main
/*
#include <stdio.h>
int callOnMeGo(int);
// The gateway function
int callOnMeGo_cgo(int in)
{
printf("C.callOnMeGo_cgo(): called with arg = %d\n", in);
// Call the GO function
return callOnMeGo(in);
}
*/
import "C"
実行します。
開発メモです。
1. コメントとインポート "C" の間に空白行がない。
2. C.CString関数を使って、GoStringを手動で解放してCStringに変換してください。
3. CGOはprintfのような可変パラメータを使用する関数をサポートしていません。使用したい場合は、ラッパー関数m'yprintfを書き、パラメータを渡して呼び出すとよいでしょう。
4. Go は //export を使って関数を C にエクスポートすることをサポートしていますが、 注意すべき点は、export と同じファイル内で c の関数を定義してはいけないということです。
multiple definition of "xxx" compile error, if the function is very tiny, another way to declare the function is using static inline, as follows.
package gocallback
import (
"fmt"
"sync"
)
/*
extern void go_callback_int(int foo, int p1);
// normally you will have to define function or variables
// in another separate C file to avoid the multiple definition
// errors, however, using "static inline" is a nice workaround
// for simple functions like this one.
static inline void CallMyFunction(int foo) {
go_callback_int(foo, 5);
}
*/
import "C"
参考
1. https://github.com/golang/go/wiki/cgo
Go言語でのCGOの使用に関するこの記事は以上です。Go言語でのCGOの使用については、Script Houseで過去の記事を検索するか、引き続き以下の関連記事を参照してください。
関連
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン