C 언어에서 Go 언어 함수 사용하기

이재홍 http://www.pyrasis.com 2014.12.17 ~ 2015.02.07

C 파일 사용하기

이번에는 주석 형태로 C 언어 코드를 작성하지 않고 .c 파일을 따로 빼내는 방법을 알아보겠습니다. 다음은 .c 파일을 작성하는 순서입니다.


그림 63-1 .c 파일 작성 순서

예제로 두 수를 받아서 위치를 바꾸어 리턴하는 함수를 만들겠습니다. 먼저 Go 언어로 C 언어에서 사용할 swap 함수를 작성합니다 그리고 GOPATH/src/swap/swap.go 파일로 저장합니다.

GOPATH/src/swap/swap.go

//export swap
func swap(a, b C.int) (C.int, C.int) { // C 언어에서 사용할 함수, 리턴값이 두 개
	return b, a
}

C 언어에서 매개변수를 넣고, 리턴값을 사용할 수 있도록 매개변수와 리턴값의 타입을 각각 C.int로 지정합니다. 이번에는 리턴값을 2개로 만들어보겠습니다. 그리고 함수 윗 부분에 //export swap 주석을 작성하여 C 언어에서 사용할 수 있도록 합니다.

주석 부분에 extern으로 함수를 선언합니다.

GOPATH/src/swap/swap.go

/*
extern void CExample();                       // Go 언어에서 C 언어의 함수를 호출하기 위한 선언
extern struct swap_return swap(int a, int b); // C언어에서 Go 언어의 함수를 호출하기 위한 선언.
                                              // 구조체를 이용하여 두 개의 값을 리턴
*/
import "C"

Go 언어에서 .c 파일에 들어있는 CExample 함수를 호출하기 위해 extern으로 선언해줍니다. 또한, .c 파일에서 Go 언어의 swap 함수를 호출하기 위해 extern으로 선언해줍니다.

C언어는 리턴값을 한 개만 사용할 수 있으므로 Go 언어에서 리턴값을 두 개 이상 리턴할 때는 반드시 C 구조체로 정의합니다. 리턴값 구조체는 struct 함수명_return 형식입니다. 따라서 swap 함수의 리턴값 구조체는 struct swap_return이 됩니다.

다음은 swap.go 파일의 전체 소스 코드입니다.

GOPATH/src/swap/swap.go

package main

/*
extern void CExample();                       // Go 언어에서 C 언어의 함수를 호출하기 위한 선언
extern struct swap_return swap(int a, int b); // C언어에서 Go 언어의 함수를 호출하기 위한 선언.
                                              // 구조체를 이용하여 두 개의 값을 리턴
*/
import "C"

//export swap
func swap(a, b C.int) (C.int, C.int) { // C 언어에서 사용할 함수, 리턴값이 두 개
	return b, a
}

func main() {
	C.CExample()
}

이제 .c 파일을 작성합니다. 다음 내용을 GOPATH/src/swap/swap.c 파일로 저장합니다.

GOPATH/src/swap/swap.c

#include <stdio.h>
#include "_cgo_export.h" // 반드시 포함

void CExample() {
	struct swap_return s;           // 구조체로 리턴값을 받을 변수를 선언
	s = swap(1, 2);                 // Go 언어의 swap 함수 호출
	printf("%d %d\n", s.r0, s.r1);  // 첫 번째 리턴값은 r0, 두 번째 리턴값은 r1
}

C 언어 파일에서는 반드시 _cgo_export.h 헤더 파일을 포함합니다. 이 파일은 컴파일하는 동안 임시로 생성되며 현재 디렉터리에는 생성되지 않습니다.

struct swap_return s와 같이 구조체로 리턴값을 받을 변수를 선언한 뒤 Go 언어의 swap 함수를 호출합니다. 그리고 s.r0, s.r1과 같이 리턴값 구조체에서 값을 가져온 뒤 화면에 출력합니다. 즉 첫 번재 리턴값은 r0이며 두 번째 리턴값은 r1입니다.

콘솔(터미널)에서 GOPATH/src/swap 디렉터리로 이동한 뒤 다음 명령을 실행합니다(Windows에서는 명령 프롬프트 또는 PowerShell을 실행합니다). 저는 GOPATH를 /home/pyrasis/hello_project로 설정하였습니다.

~$ cd $GOPATH/src/swap
~/hello_project/src/swap$ go build swap

여기서 go build 명령으로 컴파일 할 때 go build swap.go처럼 .go 파일만 컴파일하면 에러가 발생합니다. 반드시 go build swap처럼 디렉터리 이름을 지정하여 모든 소스 파일(.go, .c)이 컴파일 되도록 실행합니다.

컴파일된 실행 파일을 실행해보면 다음과 같이 swap 함수의 리턴값이 출력됩니다.

~/hello_project/src/swap$ ./swap
2 1

저작권 안내

이 웹사이트에 게시된 모든 글의 무단 복제 및 도용을 금지합니다.
  • 블로그, 게시판 등에 퍼가는 것을 금지합니다.
  • 비공개 포스트에 퍼가는 것을 금지합니다.
  • 글 내용, 그림을 발췌 및 요약하는 것을 금지합니다.
  • 링크 및 SNS 공유는 허용합니다.

Published

01 June 2015