Go언어에서 윈도 dll을 사용할 때 BSTR이라는 데이터 형식은 조금 다르게 처리해야 한다.
BSTR은 uint16 값들의 배열을 가리키는 포인터로 생각할 수 있다.
한 가지 다른 점은 이 포인터 앞에 int32 값으로 문자열의 길이를 가지고 있다는 것이다.
이 때문에 BSTR을 Go언어의 *uint16으로 처리하는 경우 잘못된 메모리 접근(memory access violation)이 발생할 수 있다.
아래와 같은 코드는 제대로 동작할 수도 있고(길이값을 사용하지 않을 때), 아닐 수도 있다(길이값을 사용할 경우).
func WrongBstr(s string) *uint16{
return syscall.StringToUTF16Ptr(s)
}
대신에 윈도우의 SysAllocString 함수를 이용해야 한다.
var(
oleaut32 = syscall.NewLazyDLL("oleaut32.dll")
sysAllocString = oleaut32.NewProc("SysAllocString")
sysFreeString = oleaut32.NewProc("SysFreeString")
)
func SysAllocString(s string) *uint16 {
ret, _, _ := sysAllocString.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(s))))
return (*uint16)(unsafe.Pointer(ret))
}
func SysFreeString(bstr *uint16) {
sysFreeString.Call(uintptr(unsafe.Pointer(bstr)))
}
SysAllocString을 사용한 경우 SysFreeString으로 메모리를 해제해주어야 한다.
- BSTR을 요구하는 함수를 호출하는 경우, 사용 후 해제한다.
- BSTR을 반환하는 함수를 호출하는 경우, 사용 후 해제한다.
- BSTR을 반환하는 함수를 구현하는 경우 할당만하고 해제하지 않는다.