I am exploring CGO and I have run into a quirk where the size of C.int in the go runtime is 8 bytes but the C int is 4 bytes. I understand that Go ints can be 64 bits or 32 bits depending on architecture, and that C ints are always 32 bits. Is there a standard way for telling go to use 4 bytes for C.int types? I have not been able to find documentation that deals with this.
Because of this the code does not function as anticipated. It basically adds the low side to the high side of the first int. It never references the second int passed.
Thanks in advance.
Actual output:
0xc00001a0b0
0xc00001a0b8
0xc00001a0b0
0xc00001a0b4
199
0
199
main.go
package main
/*
int addNums(int *nums);
*/
import "C"
import (
"fmt"
"unsafe"
)
func main() {
var nums [2]C.int
numsPtr := (*C.int)(unsafe.Pointer(&nums))
fmt.Println(numsPtr)
*numsPtr = 199
numsPtr = (*C.int)(unsafe.Pointer(uintptr(unsafe.Pointer(numsPtr)) + unsafe.Sizeof(numsPtr)))
fmt.Println(numsPtr)
*numsPtr = 3
res, err := C.addNums((*C.int)(unsafe.Pointer(&nums[0])))
if err != nil {
fmt.Println(err)
}
fmt.Println(res)
}
lib.c
long addNums(int *nums)
{
printf("%p
", &nums[0]);
printf("%p
", &nums[1]);
printf("%d
", nums[0]);
printf("%d
", nums[1]);
return (nums[0] + nums[1]);
}
I figured it out. Silly mistake. I am incrementing by the size of the pointer - 64bit address - rather than the size of the int. Revised go file:
package main
/*
int addNums(int *nums);
*/
import "C"
import (
"fmt"
"unsafe"
)
func main() {
var nums [2]int32
fmt.Println(unsafe.Sizeof(nums))
numsPtr := (*C.int)(unsafe.Pointer(uintptr(unsafe.Pointer(&nums))))
fmt.Println(numsPtr)
*numsPtr = 199
numsPtr = (*C.int)(unsafe.Pointer(uintptr(unsafe.Pointer(numsPtr)) + unsafe.Sizeof(*numsPtr)))
fmt.Println(numsPtr)
*numsPtr = 3
res, err := C.addNums((*C.int)(unsafe.Pointer(&nums)))
if err != nil {
fmt.Println(err)
}
fmt.Println(res)
}