- 책 또는 웹사이트의 내용을 복제하여 다른 곳에 게시하는 것을 금지합니다.
- 책 또는 웹사이트의 내용을 발췌, 요약하여 강의 자료, 발표 자료, 블로그 포스팅 등으로 만드는 것을 금지합니다.
C 언어에서 Go 언어 함수 사용하기
이재홍 http://www.pyrasis.com 2014.12.17 ~ 2015.02.07
C 언어와 Go 언어 사이에 콜백 구현하기
이번에는 C 언어와 Go 언어 사이에 콜백을 구현해보겠습니다. 먼저 함수의 호출 순서는 다음과 같습니다.
package main
/*
extern void goCallback(void *p, int n); // Go 언어의 함수는 extern으로 선언
static inline void CExample(void *p) { // 함수 포인터를 매개변수로 받음
goCallback(p, 100); // 받은 함수 포인터를 그대로 넣어줌
}
*/
import "C"
import (
"fmt"
"unsafe"
)
//export goCallback
func goCallback(p unsafe.Pointer, n C.int) { // C 언어에서 넘겨준 void *는
// unsafe.Pointer로 받음
f := *(*func(C.int))(p) // p를 함수 포인터 타입으로 변환한 뒤 역참조
f(n) // 함수 f 호출
}
func main() {
f := func(n C.int) { // 매개변수로 C.int를 받는 함수
fmt.Println(n)
}
C.CExample(unsafe.Pointer(&f)) // 함수 f의 포인터를 unsafe.Pointer로 변환하여 넣어줌
}
main 함수 부분을 보면 함수 f를 정의한 뒤 f의 레퍼런스(포인터)를 unsafe.Pointer 타입으로 변환하여 C.CExample에 넣어줍니다. 이렇게 하면 C언어에서 void *
타입으로 받을 수 있습니다.
f := func(n C.int) { // 매개변수로 C.int를 받는 함수
fmt.Println(n)
}
C.CExample(unsafe.Pointer(&f)) // 함수 f의 포인터를 unsafe.Pointer로 변환하여 넣어줌
주석 부분에서 C 언어로 함수를 작성합니다.
/*
extern void goCallback(void *p, int n); // Go 언어의 함수는 extern으로 선언
static inline void CExample(void *p) { // 함수 포인터를 매개변수로 받음
goCallback(p, 100); // 받은 함수 포인터를 그대로 넣어줌
}
*/
import "C"
CExample 함수는 Go 언어에서 함수 포인터를 받을 것이므로 매개변수를 void * 타입으로 지정하고, 받은 함수 포인터를 그대로 goCallback 함수에 넣어줍니다. 그리고 Go 언어의 함수 goCallback도 마찬가지로 매개변수를 void * 타입으로 받으며 extern으로 선언해줍니다.
Go 언어에서 goCallback 함수를 작성합니다.
//export goCallback
func goCallback(p unsafe.Pointer, n C.int) { // C 언어에서 넘겨준 void *는
// unsafe.Pointer로 받음
f := *(*func(C.int))(p) // p를 함수 포인터 타입으로 변환한 뒤 역참조
f(n) // 함수 f 호출
}
C 언어에서 void * 타입으로 함수 포인터를 넘겨주면 Go 언어에서는 unsafe.Pointer로 받습니다. 매개변수로 받은 p에서 함수를 꺼낼 때 문법이 복잡해보이지만 실제로는 간단합니다. 최종적으로 호출할 Go 언어의 함수는 C.int 형 매개변수 하나만 받으므로 func(C.int)이고, 이 함수의 포인터를 넘겨주었으므로 *func(C.int)이 됩니다. p를 함수 포인터 타입으로 변환한 뒤 역참조하여 f를 가져옵니다. 그리고 함수 f를 가져왔으면 매개변수로 받은 숫자 n을 넣어서 호출합니다.
소스 파일을 컴파일하여 실행을 해보면 main 함수의 f에서 fmt.Println으로 100이 출력됩니다.
100
즉 함수의 실행 순서는 main → C.CExample → goCallback → f입니다.
저작권 안내
이 웹사이트에 게시된 모든 글의 무단 복제 및 도용을 금지합니다.- 블로그, 게시판 등에 퍼가는 것을 금지합니다.
- 비공개 포스트에 퍼가는 것을 금지합니다.
- 글 내용, 그림을 발췌 및 요약하는 것을 금지합니다.
- 링크 및 SNS 공유는 허용합니다.