C 언어 연동하기


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



C 언의의 구조체 및 문자열 포인터 사용하기

이번에는 C 언어의 구조체 및 문자열 포인터에 메모리를 할당한 뒤 해제해보겠습니다.

package main

/*
#include <stdlib.h>

typedef struct _PERSON {
	char *name; // 문자열 포인터
	int age;    // 정수
} PERSON;

PERSON* create(char *name, int age) // 메모리 할당 함수 작성
{
	PERSON *p = (PERSON *)malloc(sizeof(PERSON)); // PERSON 크기로 메모리 할당

	p->name = name; // 값 설정
	p->age = age;   // 값 설정

	return p; // 할당한 메모리 리턴
}
*/
import "C"
import (
	"fmt"
	"unsafe"
)

func main() {
	var p *C.PERSON

	name := C.CString("Maria")
	age := C.int(20)

	p = C.create(name, age)

	fmt.Println(C.GoString(p.name)) // Maria: char *는 C.GoString 함수로 변환하여 사용
	fmt.Println(p.age)              // 20

	C.free(unsafe.Pointer(name)) // C.CString으로 만든 문자열은 반드시 해제
	C.free(unsafe.Pointer(p))    // C 언어의 malloc 함수로 할당한 메모리는 반드시 해제
}

먼저 C 언어로 문자열 포인터(char *)와 정수를 필드로 갖는 구조체를 정의하고, 메모리를 할당하는 함수를 만듭니다.

/*
#include <stdlib.h>

typedef struct _PERSON {
	char *name; // 문자열 포인터
	int age;    // 정수
} PERSON;

PERSON* create(char *name, int age) // 메모리 할당 함수 작성
{
	PERSON *p = (PERSON *)malloc(sizeof(PERSON)); // PERSON 크기로 메모리 할당

	p->name = name; // 값 설정
	p->age = age;   // 값 설정

	return p; // 할당한 메모리 리턴
}
*/
import "C"

create 함수에서는 malloc 함수로 PERSON 구조체 크기의 메모리를 할당합니다. 그리고 매개변수로 받은 name 포인터와 age 변수를 대입합니다. name 포인터는 C 언어에서 할당하지 않고 Go 언어에서 할당하겠습니다.

이제 C 언어에서 정의한 PERSON 구조체와 create 함수를 Go 언어에서 사용합니다.

var p *C.PERSON

name := C.CString("Maria")
age := C.int(20)

p = C.create(name, age)

fmt.Println(C.GoString(p.name)) // Maria: char *는 C.GoString 함수로 변환하여 사용
fmt.Println(p.age)              // 20

C.free(unsafe.Pointer(name)) // C.CString으로 만든 문자열은 반드시 해제
C.free(unsafe.Pointer(p))    // C 언어의 malloc 함수로 할당한 메모리는 반드시 해제

C.CString 함수는 문자열을 메모리를 할당한 뒤 C 언어의 문자열 포인터(char *)로 리턴합니다. 따라서 Go 언어에서는 바로 사용할 수 없으므로 C.GoString(p.name)과 같이 변환을 하여 사용합니다.

C.create 함수에 이름과 나이를 넣어주면 *C.PERSON 타입의 포인터가 리턴됩니다. 그리고 이 포인터를 Go 언어 변수에 대입했으므로 p.name, p.age처럼 . (점)으로 구조체 필드에 접근할 수 있습니다. 여기서 C.CString으로 만든 문자열 포인터나 C 언어의 malloc 함수로 할당한 포인터는 Go 언어의 가비지 컬렉터로 관리되지 않으므로 반드시 C 언어의 free 함수로 해제해야 합니다.

Go 언어에서는 C 언어에서 메모리를 해제할 때는 C.free(unsafe.Pointer(p))처럼 unsafe.Pointer로 변환하여 C.free 함수에 넣어줍니다.


저작권 안내

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

Published

01 June 2015