mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-23 18:52:09 +01:00
ffi: Treat enums as 32 bit signed values to fix PPC64
To call a function dynamically using ffi, the caller first has to tell ffi the size of all the input arguments of the function. On little endian architectures (like x86_64) specifying a size that's too large will happen to work because of how the bits are laid out in memory. On big endian architectures, however, specifying the wrong size can lead to reading the wrong bits. The function g_type_info_get_ffi_type maps input giargument types to specific sizes. It was assuming enums were word (pointer) sized; in fact they can be in theory any size (1,2,4,8 bytes), but in practice in introspection (via GIArgument) as well as GValue we're limited to 4 byte enums. This commit fixes PPC64 (big endian, 64 bit). Signed-off-by: Colin Walters <walters@verbum.org> https://bugzilla.gnome.org/show_bug.cgi?id=665150
This commit is contained in:
parent
cfcbd719ea
commit
c99df8f34c
60
girffi.c
60
girffi.c
@ -30,16 +30,10 @@
|
||||
#include "girepository.h"
|
||||
#include "girepository-private.h"
|
||||
|
||||
/**
|
||||
* gi_type_tag_get_ffi_type:
|
||||
* @tag: A #GITypeTag
|
||||
* @is_pointer: Whether or not this is a pointer type
|
||||
*
|
||||
* Returns: A #ffi_type corresponding to the platform default C ABI for @tag and @is_pointer.
|
||||
*/
|
||||
ffi_type *
|
||||
gi_type_tag_get_ffi_type (GITypeTag tag,
|
||||
gboolean is_pointer)
|
||||
static ffi_type *
|
||||
gi_type_tag_get_ffi_type_internal (GITypeTag tag,
|
||||
gboolean is_pointer,
|
||||
gboolean is_enum)
|
||||
{
|
||||
switch (tag)
|
||||
{
|
||||
@ -77,12 +71,21 @@ gi_type_tag_get_ffi_type (GITypeTag tag,
|
||||
case GI_TYPE_TAG_UTF8:
|
||||
case GI_TYPE_TAG_FILENAME:
|
||||
case GI_TYPE_TAG_ARRAY:
|
||||
case GI_TYPE_TAG_INTERFACE:
|
||||
case GI_TYPE_TAG_GLIST:
|
||||
case GI_TYPE_TAG_GSLIST:
|
||||
case GI_TYPE_TAG_GHASH:
|
||||
case GI_TYPE_TAG_ERROR:
|
||||
return &ffi_type_pointer;
|
||||
case GI_TYPE_TAG_INTERFACE:
|
||||
{
|
||||
/* We need to handle enums specially:
|
||||
* https://bugzilla.gnome.org/show_bug.cgi?id=665150
|
||||
*/
|
||||
if (!is_enum)
|
||||
return &ffi_type_pointer;
|
||||
else
|
||||
return &ffi_type_sint32;
|
||||
}
|
||||
case GI_TYPE_TAG_VOID:
|
||||
if (is_pointer)
|
||||
return &ffi_type_pointer;
|
||||
@ -95,6 +98,20 @@ gi_type_tag_get_ffi_type (GITypeTag tag,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gi_type_tag_get_ffi_type:
|
||||
* @tag: A #GITypeTag
|
||||
* @is_pointer: Whether or not this is a pointer type
|
||||
*
|
||||
* Returns: A #ffi_type corresponding to the platform default C ABI for @tag and @is_pointer.
|
||||
*/
|
||||
ffi_type *
|
||||
gi_type_tag_get_ffi_type (GITypeTag tag,
|
||||
gboolean is_pointer)
|
||||
{
|
||||
return gi_type_tag_get_ffi_type_internal (tag, is_pointer, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_type_info_get_ffi_type:
|
||||
* @info: A #GITypeInfo
|
||||
@ -104,7 +121,26 @@ gi_type_tag_get_ffi_type (GITypeTag tag,
|
||||
ffi_type *
|
||||
g_type_info_get_ffi_type (GITypeInfo *info)
|
||||
{
|
||||
return gi_type_tag_get_ffi_type (g_type_info_get_tag (info), g_type_info_is_pointer (info));
|
||||
gboolean is_enum;
|
||||
GIBaseInfo *iinfo;
|
||||
|
||||
if (g_type_info_get_tag (info) == GI_TYPE_TAG_INTERFACE)
|
||||
{
|
||||
iinfo = g_type_info_get_interface (info);
|
||||
switch (g_base_info_get_type (iinfo))
|
||||
{
|
||||
case GI_INFO_TYPE_ENUM:
|
||||
case GI_INFO_TYPE_FLAGS:
|
||||
is_enum = TRUE;
|
||||
break;
|
||||
default:
|
||||
is_enum = FALSE;
|
||||
break;
|
||||
}
|
||||
g_base_info_unref (iinfo);
|
||||
}
|
||||
|
||||
return gi_type_tag_get_ffi_type_internal (g_type_info_get_tag (info), g_type_info_is_pointer (info), is_enum);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user