c-for-go icon indicating copy to clipboard operation
c-for-go copied to clipboard

Arch-specific options for integer type mapping

Open XuehaiPan opened this issue 3 years ago • 1 comments

Firstly, thanks for creating and maintaining such a useful utility.

I found commit https://github.com/xlab/c-for-go/commit/ddcfe2673053652b6566fa8fabe6d0966a6b4ed9 changes the default type mapping for long and int type. Indeed, unless the size is explicitly specified (e.g. uint64_t), the sizes of types int / unsigned int / long / unsigned long are arch-specific and implementation-specific. The change in commit https://github.com/xlab/c-for-go/commit/ddcfe2673053652b6566fa8fabe6d0966a6b4ed9 seems to be correct.

However, such changes will break the signature of existing Go bindings between versions (https://github.com/NVIDIA/go-nvml/issues/31#issuecomment-981449209). If the user wants to generate bindings for a specific platform (e.g. x86_64_linux), type unsigned long should be translated to uint or uint64 type.

Should we make this mapping to be arch-specific (wiki/Parser-config-section#arch)?

https://github.com/xlab/c-for-go/blob/291d167cff5752d6cc5b4c369c326cd5ac61367a/parser/predefined.go#L81-L104

Or is there a way to add some option in the configuration to customize it?

Related issue NVIDIA/go-nvml#31.

XuehaiPan avatar Dec 01 '21 08:12 XuehaiPan

C snippet:

#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

// User defined function in C
void printf_ulong(unsigned long *x)
{
	*x = (unsigned long)UINT32_MAX + 1;
	printf("Value in     function: %lu\n", *x);
}

// Binding in Golang
void go_binding()
{
	uint64_t value64 = 0;
	printf("Value before function: %lu\n", value64);
	printf_ulong((unsigned long *)&value64);
	printf("Value after  function: %lu\n", value64);
}

int main()
{
	go_binding();
	return 0;
}

On x86_64 Linux machine (Ubuntu 20.04 LTS), compile and run with g++ 9.3.0:

$ uname -io 
x86_64 GNU/Linux

$ gcc --version
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ gcc -std=c99 "test.c" -o "test" && { ./"test"; rm "test" }
Value before function: 0
Value in     function: 4294967296
Value after  function: 4294967296

C snippet (change types to uint32_t but keep the function input type as unsigned long):

#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

// User defined function in C
void printf_ulong(unsigned long *x)
{
	*x = (unsigned long)UINT32_MAX + 1;
	printf("Value in     function: %lu\n", *x);
}

// Binding in Golang
void go_binding()
{
	uint32_t value32 = 0;
	printf("Value before function: %u\n", value32);
	printf_ulong((unsigned long *)&value32);
	printf("Value after  function: %u\n", value32);
}

int main()
{
	go_binding();
	return 0;
}

Got errors:

$ gcc -std=c99 "test.c" -o "test" && { ./"test"; rm "test" }
Value before function: 0
Value in     function: 4294967296
Value after  function: 0
*** stack smashing detected ***: terminated

XuehaiPan avatar Dec 01 '21 08:12 XuehaiPan