diff --git a/build.xml b/build.xml
index f29dc5f..ee45946 100644
--- a/build.xml
+++ b/build.xml
@@ -72,7 +72,7 @@
-
+
diff --git a/native/Makefile b/native/Makefile
index 1f0ea70..02d4c7d 100644
--- a/native/Makefile
+++ b/native/Makefile
@@ -48,7 +48,7 @@ OS=$(shell uname | sed -e 's/CYGWIN.*/win32/g' \
-e 's/Linux.*/linux/g')
JNA_JNI_VERSION=4.0.0 # auto-generated by ant
-CHECKSUM=1a6047467b59e8748f975e03016ce3d9 # auto-generated by ant
+CHECKSUM=3f99b7ecf15cd6a6fc62cc9420598381 # auto-generated by ant
JAVA_INCLUDES=-I"$(JAVA_HOME)/include" \
-I"$(JAVA_HOME)/include/$(OS)"
@@ -63,7 +63,7 @@ ifneq ($(DYNAMIC_LIBFFI),true)
FFI_SRC=$(shell pwd)/libffi
FFI_BUILD=$(BUILD)/libffi
FFI_LIB=$(FFI_BUILD)/.libs/libffi$(ARSFX)
-FFI_ENV=CC="$(CC)" CFLAGS="$(COPT) $(CDEBUG)" CPPFLAGS="$(CDEFINES)"
+FFI_ENV=CC="$(CC)" CFLAGS="$(COPT) $(CDEBUG) -std=gnu99" CPPFLAGS="$(CDEFINES)"
FFI_CONFIG=--enable-static --disable-shared --with-pic=yes
endif
LIBRARY=$(BUILD)/$(LIBPFX)jnidispatch$(JNISFX)
@@ -91,7 +91,7 @@ CFLAGS_EXTRA=
COUT=-o $@
CINCLUDES=$(JAVA_INCLUDES) -I"$(JAVAH)" -I$(FFI_BUILD)/include
CDEFINES=-D_REENTRANT
-PCFLAGS=-W -Wall -Wno-unused -Wno-parentheses
+PCFLAGS=-W -std=gnu99 -Wall -Wno-unused -Wno-parentheses
CFLAGS=$(PCFLAGS) $(CFLAGS_EXTRA) $(COPT) $(CDEBUG) $(CDEFINES) $(CINCLUDES) \
-DJNA_JNI_VERSION='"$(JNA_JNI_VERSION)"' -DCHECKSUM='"$(CHECKSUM)"'
LDFLAGS=-o $@ -shared
@@ -132,7 +132,7 @@ JAVA_INCLUDES=
CINCLUDES+=-I"$(NDK_PLATFORM)/arch-$(ARCH)/usr/include" # -I/usr/include
LIBS=-nostdlib -L"$(NDK_PLATFORM)/arch-$(ARCH)/usr/lib/" -lgcc -lc -ldl -lm
LDFLAGS+=-Wl,-shared,-Bsymbolic
-FFI_ENV=CPP="$(CPP)" CC="$(CC)" CFLAGS="$(COPT) $(CDEBUG) $(CINCLUDES)" CPPFLAGS="$(CDEFINES) $(CINCLUDES)" LIBS="$(LIBS)" RANLIB="$(RANLIB)"
+FFI_ENV=CPP="$(CPP)" CC="$(CC)" CFLAGS="$(COPT) $(CDEBUG) $(CINCLUDES) -std=gnu99" CPPFLAGS="$(CDEFINES) $(CINCLUDES)" LIBS="$(LIBS)" RANLIB="$(RANLIB)"
FFI_CONFIG=--enable-static --disable-shared --with-pic=yes --host=$(HOST)
endif
@@ -273,7 +273,7 @@ endif
ifeq ($(OS),aix)
LIBSFX=.a
PCFLAGS+=-fPIC
-CDEFINES+=-DHAVE_PROTECTION -DNO_JAWT -Wall -D_AIX -DPOWERPC_AIX -D_THREAD_SAFE_ERRNO
+CDEFINES+=-DHAVE_PROTECTION -DNO_JAWT -std=gnu99 -Wall -D_AIX -DPOWERPC_AIX -D_THREAD_SAFE_ERRNO
COPT+=-D_AIX -DPOWERPC_AIX -mxl-compat
LDFLAGS+=-Wl,-lc128,-lc,-lm,-lpthread
FFI_ENV+=AR_FLAGS="-X32_64 cru"
@@ -322,7 +322,7 @@ JAVA_INCLUDES=-I/System/Library/Frameworks/JavaVM.framework/Headers
DEFAULT_ARCH=$(shell arch)
ARCH=$(shell arch)
HOST_CONFIG=--host $(ARCH)-apple-darwin
-FFI_ENV += CC="$(CC)" CFLAGS="-arch $(ARCH) $(ISYSROOT) $(COPT) $(CDEBUG)" CPPFLAGS="$(CDEFINES)" LD="$(LD) -arch $(ARCH)"
+FFI_ENV += CC="$(CC)" CFLAGS="-arch $(ARCH) $(ISYSROOT) $(COPT) $(CDEBUG) -std=gnu99" CPPFLAGS="$(CDEFINES)" LD="$(LD) -arch $(ARCH)"
ALT_ARCHS=
ifneq ($(ARCH),i386)
ALT_ARCHS+=i386
@@ -431,7 +431,7 @@ ifneq ($(SDKROOT),)
if [ ! -f $(BUILD)/libffi.$$arch/Makefile ]; then \
echo "Configuring libffi ($$arch)"; \
(cd $(BUILD)/libffi.$$arch \
- && CC="$(CC)" CFLAGS="-arch $$arch $(ISYSROOT) $(COPT) $(CDEBUG)" CPPFLAGS="$(CDEFINES)" \
+ && CC="$(CC)" CFLAGS="-arch $$arch $(ISYSROOT) $(COPT) $(CDEBUG) -std=gnu99" CPPFLAGS="$(CDEFINES)" \
LDFLAGS="-arch $$arch" \
$(FFI_SRC)/configure $(FFI_CONFIG) --host=$$arch-apple-darwin --disable-dependency-tracking); \
fi; \
diff --git a/native/callback.c b/native/callback.c
index a4ccf5e..b311f3f 100644
--- a/native/callback.c
+++ b/native/callback.c
@@ -379,7 +379,7 @@ callback_invoke(JNIEnv* env, callback *cb, ffi_cif* cif, void *resp, void **cbar
*((void **)args[i+3]) = fromNative(env, cb->arg_classes[i], cif->arg_types[i], cbargs[i], JNI_FALSE);
break;
case CVT_POINTER:
- *((void **)args[i+3]) = newJavaPointer(env, *(void **)cbargs[i]);
+ *((void **)args[i+3]) = newJavaPointer(env, *(void **)cbargs[i], cif);
break;
case CVT_STRING:
*((void **)args[i+3]) = newJavaString(env, *(void **)cbargs[i], cb->encoding);
@@ -476,7 +476,7 @@ callback_invoke(JNIEnv* env, callback *cb, ffi_cif* cif, void *resp, void **cbar
unsigned int i;
for (i=0;i < cif->nargs;i++) {
- jobject arg = new_object(env, cb->arg_jtypes[i], cbargs[i], JNI_FALSE);
+ jobject arg = new_object(env, cb->arg_jtypes[i], cbargs[i], JNI_FALSE, cif);
(*env)->SetObjectArrayElement(env, array, i, arg);
}
result = (*env)->CallObjectMethod(env, self, cb->methodID, array);
diff --git a/native/dispatch.c b/native/dispatch.c
index 71fd083..e6fa505 100644
--- a/native/dispatch.c
+++ b/native/dispatch.c
@@ -208,6 +208,7 @@ static jfieldID FID_Float_value;
static jfieldID FID_Double_value;
static jfieldID FID_Pointer_peer;
+static jfieldID FID_Pointer_cif;
static jfieldID FID_Structure_memory;
static jfieldID FID_Structure_typeInfo;
static jfieldID FID_IntegerType_value;
@@ -875,11 +876,11 @@ newJavaString(JNIEnv *env, const char *ptr, const char* charset)
}
jobject
-newJavaPointer(JNIEnv *env, void *p)
+newJavaPointer(JNIEnv *env, void *p, ffi_cif *cif)
{
jobject obj = NULL;
if (p != NULL) {
- obj = (*env)->NewObject(env, classPointer, MID_Pointer_init, A2L(p));
+ obj = (*env)->NewObject(env, classPointer, MID_Pointer_init, A2L(p), cif == NULL ? 0 : A2L(cif));
}
return obj;
}
@@ -901,7 +902,7 @@ jobject
newJavaCallback(JNIEnv* env, void* fptr, jclass type)
{
if (fptr != NULL) {
- jobject ptr = newJavaPointer(env, fptr);
+ jobject ptr = newJavaPointer(env, fptr, NULL);
return (*env)->CallStaticObjectMethod(env, classCallbackReference,
MID_CallbackReference_getCallback,
type, ptr, JNI_TRUE);
@@ -1139,7 +1140,7 @@ toNativeTypeMapped(JNIEnv* env, jobject obj, void* valuep, size_t size, jobject
static void
fromNativeTypeMapped(JNIEnv* env, jobject from_native, void* resp, ffi_type* type, jclass javaClass, void* result) {
int jtype = get_jtype_from_ffi_type(type);
- jobject value = new_object(env, (char)jtype, resp, JNI_TRUE);
+ jobject value = new_object(env, (char)jtype, resp, JNI_TRUE, NULL);
if (!(*env)->ExceptionCheck(env)) {
jobject obj = (*env)->CallStaticObjectMethod(env, classNative,
MID_Native_fromNativeTypeMapped,
@@ -1156,7 +1157,7 @@ fromNativeTypeMapped(JNIEnv* env, jobject from_native, void* resp, ffi_type* typ
jobject
fromNative(JNIEnv* env, jclass javaClass, ffi_type* type, void* resp, jboolean promote) {
int jtype = get_jtype_from_ffi_type(type);
- jobject value = new_object(env, (char)jtype, resp, promote);
+ jobject value = new_object(env, (char)jtype, resp, promote, NULL);
if (!(*env)->ExceptionCheck(env)) {
return (*env)->CallStaticObjectMethod(env, classNative,
MID_Native_fromNative,
@@ -1516,12 +1517,12 @@ extract_value(JNIEnv* env, jobject value, void* resp, size_t size, jboolean prom
/** Construct a new Java object from a native value. */
jobject
-new_object(JNIEnv* env, char jtype, void* valuep, jboolean promote) {
+new_object(JNIEnv* env, char jtype, void* valuep, jboolean promote, ffi_cif *cif) {
switch(jtype) {
case 's':
- return newJavaPointer(env, valuep);
+ return newJavaPointer(env, valuep, cif);
case '*':
- return newJavaPointer(env, *(void**)valuep);
+ return newJavaPointer(env, *(void**)valuep, cif);
case 'J':
return (*env)->NewObject(env, classLong, MID_Long_init,
*(jlong *)valuep);
@@ -1693,7 +1694,7 @@ method_handler(ffi_cif* cif, void* volatile resp, void** argp, void *cdata) {
int jtype = get_jtype_from_ffi_type(data->closure_cif.arg_types[i+2]);
jobject obj = jtype == '*'
? *(void **)valuep
- : new_object(env, (char)jtype, valuep, JNI_FALSE);
+ : new_object(env, (char)jtype, valuep, JNI_FALSE, cif);
if (cif->arg_types[i+2]->size < data->cif.arg_types[i]->size) {
args[i] = alloca(data->cif.arg_types[i]->size);
}
@@ -1814,7 +1815,7 @@ method_handler(ffi_cif* cif, void* volatile resp, void** argp, void *cdata) {
*(void **)oldresp = fromNative(env, data->closure_rclass, data->cif.rtype, resp, JNI_TRUE);
break;
case CVT_POINTER:
- *(void **)resp = newJavaPointer(env, *(void **)resp);
+ *(void **)resp = newJavaPointer(env, *(void **)resp, cif);
break;
case CVT_STRING:
*(void **)resp = newJavaString(env, *(void **)resp, data->encoding);
@@ -2655,7 +2656,7 @@ Java_com_sun_jna_Native_initIDs(JNIEnv *env, jclass cls) {
"Can't obtain class com.sun.jna.Pointer");
}
else if (!LOAD_MID(env, MID_Pointer_init, classPointer,
- "", "(J)V")) {
+ "", "(JJ)V")) {
throwByName(env, EUnsatisfiedLink,
"Can't obtain constructor for class com.sun.jna.Pointer");
}
@@ -2663,6 +2664,10 @@ Java_com_sun_jna_Native_initIDs(JNIEnv *env, jclass cls) {
throwByName(env, EUnsatisfiedLink,
"Can't obtain peer field ID for class com.sun.jna.Pointer");
}
+ else if (!LOAD_FID(env, FID_Pointer_cif, classPointer, "cif", "J")) {
+ throwByName(env, EUnsatisfiedLink,
+ "Can't obtain libffi cif field ID for class com.sun.jna.Pointer");
+ }
else if (!(classNative = (*env)->NewWeakGlobalRef(env, cls))) {
throwByName(env, EUnsatisfiedLink,
"Can't obtain global reference for class com.sun.jna.Native");
@@ -2839,7 +2844,7 @@ Java_com_sun_jna_Native_initIDs(JNIEnv *env, jclass cls) {
throwByName(env, EUnsatisfiedLink, field);
return;
}
- (*env)->SetStaticObjectField(env, cls, fid, newJavaPointer(env, types[i]));
+ (*env)->SetStaticObjectField(env, cls, fid, newJavaPointer(env, types[i], NULL));
}
}
}
@@ -3352,6 +3357,87 @@ Java_com_sun_jna_Native_setDetachState(JNIEnv* env, jclass UNUSED(cls), jboolean
JNA_detach(env, d, L2A(flag));
}
+/* libffi variadic closure functions */
+
+JNIEXPORT jbyte JNICALL
+Java_com_sun_jna_Native_ffi_1closure_1va_1sint8(JNIEnv *env, jclass UNUSED(cls), jlong cif)
+{
+ return ffi_closure_va_sint8(L2A(cif));
+}
+
+JNIEXPORT jshort JNICALL
+Java_com_sun_jna_Native_ffi_1closure_1va_1sint16(JNIEnv *env, jclass UNUSED(cls), jlong cif)
+{
+ return ffi_closure_va_sint16(L2A(cif));
+}
+
+JNIEXPORT jint JNICALL
+Java_com_sun_jna_Native_ffi_1closure_1va_1sint32(JNIEnv *env, jclass UNUSED(cls), jlong cif)
+{
+ return ffi_closure_va_sint32(L2A(cif));
+}
+
+JNIEXPORT jlong JNICALL
+Java_com_sun_jna_Native_ffi_1closure_1va_1sint64(JNIEnv *env, jclass UNUSED(cls), jlong cif)
+{
+ return ffi_closure_va_sint64(L2A(cif));
+}
+
+JNIEXPORT jbyte JNICALL
+Java_com_sun_jna_Native_ffi_1closure_1va_1uint8(JNIEnv *env, jclass UNUSED(cls), jlong cif)
+{
+ return ffi_closure_va_uint8(L2A(cif));
+}
+
+JNIEXPORT jchar JNICALL
+Java_com_sun_jna_Native_ffi_1closure_1va_1uint16(JNIEnv *env, jclass UNUSED(cls), jlong cif)
+{
+ return ffi_closure_va_uint16(L2A(cif));
+}
+
+JNIEXPORT jint JNICALL
+Java_com_sun_jna_Native_ffi_1closure_1va_1uint32(JNIEnv *env, jclass UNUSED(cls), jlong cif)
+{
+ return ffi_closure_va_uint32(L2A(cif));
+}
+
+JNIEXPORT jlong JNICALL
+Java_com_sun_jna_Native_ffi_1closure_1va_1uint64(JNIEnv *env, jclass UNUSED(cls), jlong cif)
+{
+ return ffi_closure_va_uint64(L2A(cif));
+}
+
+JNIEXPORT jfloat JNICALL
+Java_com_sun_jna_Native_ffi_1closure_1va_1float(JNIEnv *env, jclass UNUSED(cls), jlong cif)
+{
+ return ffi_closure_va_float(L2A(cif));
+}
+
+JNIEXPORT jdouble JNICALL
+Java_com_sun_jna_Native_ffi_1closure_1va_1double(JNIEnv *env, jclass UNUSED(cls), jlong cif)
+{
+ return ffi_closure_va_double(L2A(cif));
+}
+
+JNIEXPORT jlong JNICALL
+Java_com_sun_jna_Native__1ffi_1closure_1va_1slong(JNIEnv *env, jclass UNUSED(cls), jlong cif)
+{
+ return ffi_closure_va_slong(L2A(cif));
+}
+
+JNIEXPORT jlong JNICALL
+Java_com_sun_jna_Native__1ffi_1closure_1va_1ulong(JNIEnv *env, jclass UNUSED(cls), jlong cif)
+{
+ return ffi_closure_va_ulong(L2A(cif));
+}
+
+JNIEXPORT jlong JNICALL
+Java_com_sun_jna_Native__1ffi_1closure_1va_1pointer(JNIEnv *env, jclass UNUSED(cls), jlong cif)
+{
+ void *result = ffi_closure_va_pointer(L2A(cif));
+ return A2L(result);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/native/dispatch.h b/native/dispatch.h
index 602b304..71da754 100644
--- a/native/dispatch.h
+++ b/native/dispatch.h
@@ -186,13 +186,13 @@ extern callback* create_callback(JNIEnv*, jobject, jobject,
callconv_t, jint, jstring);
extern void free_callback(JNIEnv*, callback*);
extern void extract_value(JNIEnv*, jobject, void*, size_t, jboolean);
-extern jobject new_object(JNIEnv*, char, void*, jboolean);
+extern jobject new_object(JNIEnv*, char, void*, jboolean, ffi_cif *cif);
extern jboolean is_protected();
extern int get_conversion_flag(JNIEnv*, jclass);
extern jboolean ffi_error(JNIEnv*,const char*,ffi_status);
extern const char* newCStringUTF8(JNIEnv*, jstring);
-extern jobject newJavaPointer(JNIEnv*, void*);
+extern jobject newJavaPointer(JNIEnv*, void*, ffi_cif*);
extern jstring newJavaString(JNIEnv*, const char*, const char*);
extern jobject newJavaWString(JNIEnv*, const wchar_t*);
extern jobject newJavaStructure(JNIEnv*, void*, jclass);
diff --git a/native/libffi/Makefile.am b/native/libffi/Makefile.am
index bf0156f..4218cd1 100644
--- a/native/libffi/Makefile.am
+++ b/native/libffi/Makefile.am
@@ -102,7 +102,8 @@ toolexeclib_LTLIBRARIES = libffi.la
noinst_LTLIBRARIES = libffi_convenience.la
libffi_la_SOURCES = src/prep_cif.c src/types.c \
- src/raw_api.c src/java_raw_api.c src/closures.c
+ src/raw_api.c src/java_raw_api.c src/closures.c \
+ src/closures_va.c
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libffi.pc
diff --git a/native/libffi/Makefile.in b/native/libffi/Makefile.in
index 4b6abe5..7b50c7a 100644
--- a/native/libffi/Makefile.in
+++ b/native/libffi/Makefile.in
@@ -149,7 +149,7 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) $(toolexeclib_LTLIBRARIES)
libffi_la_LIBADD =
am__dirstamp = $(am__leading_dot)dirstamp
am_libffi_la_OBJECTS = src/prep_cif.lo src/types.lo src/raw_api.lo \
- src/java_raw_api.lo src/closures.lo
+ src/java_raw_api.lo src/closures.lo src/closures_va.lo
@FFI_DEBUG_TRUE@am__objects_1 = src/debug.lo
@MIPS_TRUE@am__objects_2 = src/mips/ffi.lo src/mips/o32.lo \
@MIPS_TRUE@ src/mips/n32.lo
@@ -217,7 +217,7 @@ libffi_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libffi_la_LDFLAGS) $(LDFLAGS) -o $@
libffi_convenience_la_LIBADD =
am__objects_35 = src/prep_cif.lo src/types.lo src/raw_api.lo \
- src/java_raw_api.lo src/closures.lo
+ src/java_raw_api.lo src/closures.lo src/closures_va.lo
am_libffi_convenience_la_OBJECTS = $(am__objects_35)
am__objects_36 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \
$(am__objects_4) $(am__objects_5) $(am__objects_6) \
@@ -556,7 +556,8 @@ MAKEOVERRIDES =
toolexeclib_LTLIBRARIES = libffi.la
noinst_LTLIBRARIES = libffi_convenience.la
libffi_la_SOURCES = src/prep_cif.c src/types.c \
- src/raw_api.c src/java_raw_api.c src/closures.c
+ src/raw_api.c src/java_raw_api.c src/closures.c \
+ src/closures_va.c
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libffi.pc
@@ -690,6 +691,7 @@ src/types.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/raw_api.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/java_raw_api.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/closures.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+src/closures_va.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/debug.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/mips/$(am__dirstamp):
@$(MKDIR_P) src/mips
@@ -1017,6 +1019,7 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/closures.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/closures_va.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/debug.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/java_raw_api.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/prep_cif.Plo@am__quote@
diff --git a/native/libffi/include/ffi.h.in b/native/libffi/include/ffi.h.in
index a51583b..78d4d5e 100644
--- a/native/libffi/include/ffi.h.in
+++ b/native/libffi/include/ffi.h.in
@@ -75,6 +75,11 @@ extern "C" {
#include
#include
+/* C99 int data types */
+#if __STDC_VERSION__ >= 199901L
+# include
+#endif
+
/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
But we can find it either under the correct ANSI name, or under GNU
C's internal name. */
@@ -219,8 +224,18 @@ typedef struct {
#ifdef FFI_EXTRA_CIF_FIELDS
FFI_EXTRA_CIF_FIELDS;
#endif
+#ifdef FFI_CLOSURE_VA_LIST
+ ffi_closure_va_list va;
+#endif
} ffi_cif;
+/* Used internally and used to access variadic arguments in closures */
+#ifdef FFI_CLOSURE_VA_LIST
+ffi_status ffi_closure_va_arg(ffi_cif *cif,
+ ffi_type *type,
+ void **va_value);
+#endif
+
/* Used internally, but overridden by some architectures */
ffi_status ffi_prep_cif_core(ffi_cif *cif,
ffi_abi abi,
@@ -436,6 +451,42 @@ void ffi_call(ffi_cif *cif,
/* Useful for eliminating compiler warnings */
#define FFI_FN(f) ((void (*)(void))f)
+/* ---- Definitions for variadic closures -------------------------------- */
+
+#ifdef FFI_CLOSURE_VA_LIST
+
+# if __STDC_VERSION__ >= 199901L
+/* C99 data types */
+int8_t ffi_closure_va_sint8 (ffi_cif *cif);
+int16_t ffi_closure_va_sint16 (ffi_cif *cif);
+int32_t ffi_closure_va_sint32 (ffi_cif *cif);
+int64_t ffi_closure_va_sint64 (ffi_cif *cif);
+uint8_t ffi_closure_va_uint8 (ffi_cif *cif);
+uint16_t ffi_closure_va_uint16 (ffi_cif *cif);
+uint32_t ffi_closure_va_uint32 (ffi_cif *cif);
+uint64_t ffi_closure_va_uint64 (ffi_cif *cif);
+# endif /* __STDC_VERSION__ >= 199901L */
+
+# ifndef LIBFFI_HIDE_BASIC_TYPES
+signed char ffi_closure_va_schar (ffi_cif *cif);
+short ffi_closure_va_sshort (ffi_cif *cif);
+int ffi_closure_va_sint (ffi_cif *cif);
+long ffi_closure_va_slong (ffi_cif *cif);
+unsigned char ffi_closure_va_uchar (ffi_cif *cif);
+unsigned short ffi_closure_va_ushort (ffi_cif *cif);
+unsigned int ffi_closure_va_uint (ffi_cif *cif);
+unsigned long ffi_closure_va_ulong (ffi_cif *cif);
+# endif /* ! LIBFFI_HIDE_BASIC_TYPES */
+
+float ffi_closure_va_float (ffi_cif *cif);
+double ffi_closure_va_double (ffi_cif *cif);
+void *ffi_closure_va_pointer (ffi_cif *cif);
+
+# if @HAVE_LONG_DOUBLE@
+long double ffi_closure_va_longdouble (ffi_cif *cif);
+# endif /* HAVE_LONG_DOUBLE */
+#endif /* FFI_CLOSURE_VA_LIST */
+
/* ---- Definitions shared with assembly code ---------------------------- */
#endif
diff --git a/native/libffi/include/ffi_common.h b/native/libffi/include/ffi_common.h
index 650ca69..e0dbc8e 100644
--- a/native/libffi/include/ffi_common.h
+++ b/native/libffi/include/ffi_common.h
@@ -64,10 +64,12 @@ void ffi_type_test(ffi_type *a, char *file, int line);
#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l)))
#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__)
+#define FFI_RUN_OK(x) ((x) == FFI_OK ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
#else
#define FFI_ASSERT(x)
#define FFI_ASSERT_AT(x, f, l)
#define FFI_ASSERT_VALID_TYPE(x)
+#define FFI_RUN_OK(x) ((x))
#endif
#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
diff --git a/native/libffi/src/closures_va.c b/native/libffi/src/closures_va.c
new file mode 100644
index 0000000..9d5a955
--- /dev/null
+++ b/native/libffi/src/closures_va.c
@@ -0,0 +1,168 @@
+/* -----------------------------------------------------------------------
+ closures_va.c
+
+ Code to access variadic arguments inside of closures.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ ``Software''), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+ ----------------------------------------------------------------------- */
+
+#include
+#include
+
+#if FFI_CLOSURES
+# if __STDC_VERSION__ >= 199901L
+
+/* Note: int8_t, uint8_t, int16_t and uint16_t are promoted to int in '...'
+ */
+int8_t
+ffi_closure_va_sint8(ffi_cif *cif) {
+ return ffi_closure_va_sint32(cif);
+}
+
+uint8_t
+ffi_closure_va_uint8(ffi_cif *cif) {
+ return ffi_closure_va_uint32(cif);
+}
+
+int16_t
+ffi_closure_va_sint16(ffi_cif *cif) {
+ return ffi_closure_va_sint32(cif);
+}
+
+uint16_t
+ffi_closure_va_uint16(ffi_cif *cif) {
+ return ffi_closure_va_uint32(cif);
+}
+
+int32_t
+ffi_closure_va_sint32(ffi_cif *cif) {
+ void *val;
+ FFI_RUN_OK(ffi_closure_va_arg(cif, &ffi_type_sint32, &val));
+ return *(int32_t *)val;
+}
+
+uint32_t
+ffi_closure_va_uint32(ffi_cif *cif) {
+ void *val;
+ FFI_RUN_OK(ffi_closure_va_arg(cif, &ffi_type_uint32, &val));
+ return *(uint32_t *)val;
+}
+
+int64_t
+ffi_closure_va_sint64(ffi_cif *cif) {
+ void *val;
+ FFI_RUN_OK(ffi_closure_va_arg(cif, &ffi_type_sint64, &val));
+ return *(int64_t *)val;
+}
+
+uint64_t
+ffi_closure_va_uint64(ffi_cif *cif) {
+ void *val;
+ FFI_RUN_OK(ffi_closure_va_arg(cif, &ffi_type_uint64, &val));
+ return *(uint64_t *)val;
+}
+# endif /* __STDC_VERSION__ >= 199901L */
+
+# if !defined (LIBFFI_HIDE_BASIC_TYPES)
+
+/* Note: char, uchar, short and ushort are promoted to int in '...'
+ */
+signed char
+ffi_closure_va_schar(ffi_cif *cif) {
+ return ffi_closure_va_sint(cif);
+}
+
+unsigned char
+ffi_closure_va_uchar(ffi_cif *cif) {
+ return ffi_closure_va_uint(cif);
+}
+
+short
+ffi_closure_va_sshort(ffi_cif *cif) {
+ return ffi_closure_va_sint(cif);
+}
+
+unsigned short
+ffi_closure_va_ushort(ffi_cif *cif) {
+ return ffi_closure_va_uint(cif);
+}
+
+int
+ffi_closure_va_sint(ffi_cif *cif) {
+ void *val;
+ FFI_RUN_OK(ffi_closure_va_arg(cif, &ffi_type_sint, &val));
+ return *(int *)val;
+}
+
+unsigned int
+ffi_closure_va_uint(ffi_cif *cif) {
+ void *val;
+ FFI_RUN_OK(ffi_closure_va_arg(cif, &ffi_type_uint, &val));
+ return *(unsigned int *)val;
+}
+
+long
+ffi_closure_va_slong(ffi_cif *cif) {
+ void *val;
+ FFI_RUN_OK(ffi_closure_va_arg(cif, &ffi_type_slong, &val));
+ return *(long *)val;
+}
+
+unsigned long
+ffi_closure_va_ulong(ffi_cif *cif) {
+ void *val;
+ FFI_RUN_OK(ffi_closure_va_arg(cif, &ffi_type_ulong, &val));
+ return *(unsigned long *)val;
+}
+
+# endif /* ! LIBFFI_HIDE_BASIC_TYPES */
+
+/* Note: float is promoted to double when passed through '...'
+ */
+
+float
+ffi_closure_va_float(ffi_cif *cif) {
+ return ffi_closure_va_double(cif);
+}
+
+double
+ffi_closure_va_double(ffi_cif *cif) {
+ void *val;
+ FFI_RUN_OK(ffi_closure_va_arg(cif, &ffi_type_double, &val));
+ return *(double *)val;
+}
+
+void *
+ffi_closure_va_pointer(ffi_cif *cif) {
+ void **val;
+ FFI_RUN_OK(ffi_closure_va_arg(cif, &ffi_type_pointer, (void **)&val));
+ return *val;
+}
+
+# if HAVE_LONG_DOUBLE
+long double
+ffi_closure_va_longdouble(ffi_cif *cif) {
+ void *val;
+ FFI_RUN_OK(ffi_closure_va_arg(cif, &ffi_type_longdouble, &val));
+ return *(long double *)val;
+}
+# endif /* HAVE_LONG_DOUBLE */
+#endif /* FFI_CLOSURES */
diff --git a/native/libffi/src/x86/darwin64.S b/native/libffi/src/x86/darwin64.S
index 2f7394e..26a912e 100644
--- a/native/libffi/src/x86/darwin64.S
+++ b/native/libffi/src/x86/darwin64.S
@@ -213,7 +213,7 @@ LUW6:
movq %rcx, 24(%rsp)
movq %r8, 32(%rsp)
movq %r9, 40(%rsp)
- jc Lsave_sse
+ jmp Lsave_sse /* Unconditionally load SSE registers for varargs */
Lret_from_save_sse:
movq %r10, %rdi
diff --git a/native/libffi/src/x86/ffi.c b/native/libffi/src/x86/ffi.c
index c44f4f0..e7996cc 100644
--- a/native/libffi/src/x86/ffi.c
+++ b/native/libffi/src/x86/ffi.c
@@ -502,71 +502,95 @@ ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
}
#endif /* !X86_WIN64 */
+/* This definition is shared by calls for fixed and variadic arguments.
+ * You should only check the ABI for variadic arguments.
+ */
+static ffi_status
+ffi_closure_va_arg_internal(ffi_cif *cif, ffi_type *va_type, void **va_value,
+ int checkABI)
+{
+ size_t z;
+
+ /* The callee cleans up the stack in Microsoft calling conventions
+ * stdcall, thiscall and fastcall. You cannot use vararg functions
+ * with these calling conventions.
+ * Reference: http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx
+ * and: http://msdn.microsoft.com/en-us/library/984x0h58.aspx
+ */
+ if (checkABI
+ && (cif->abi == FFI_STDCALL || cif->abi == FFI_THISCALL
+ || cif->abi == FFI_FASTCALL)) {
+ return FFI_BAD_ABI;
+ }
+
+ /* Align if necessary */
+ if ((sizeof(void*) - 1) & (size_t) cif->va.stack) {
+ cif->va.stack = (char *) ALIGN(cif->va.stack, sizeof(void*));
+ }
+
+#ifdef X86_WIN64
+ if (va_type->size > sizeof(ffi_arg)
+ || (va_type->type == FFI_TYPE_STRUCT
+ && (va_type->size != 1 && va_type->size != 2
+ && va_type->size != 4 && va_type->size != 8)))
+ {
+ z = sizeof(void *);
+ *va_value = *(void **) cif->va.stack;
+ }
+ else
+#endif
+ {
+ z = va_type->size;
+ /* because we're little endian, this is what it turns into. */
+ *va_value = (void*) cif->va.stack;
+ }
+
+#ifdef X86_WIN64
+ cif->va.stack += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
+#else
+ cif->va.stack += z;
+#endif
+
+ return FFI_OK;
+}
+
+ffi_status
+ffi_closure_va_arg(ffi_cif *cif, ffi_type *va_type, void **va_value)
+{
+ return ffi_closure_va_arg_internal(cif, va_type, va_value, 1);
+}
+
static void
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
ffi_cif *cif)
{
register unsigned int i;
- register void **p_argv;
- register char *argp;
- register ffi_type **p_arg;
- argp = stack;
+ cif->va.stack = stack;
+ /* Setup the return value */
#ifdef X86_WIN64
if (cif->rtype->size > sizeof(ffi_arg)
|| (cif->flags == FFI_TYPE_STRUCT
&& (cif->rtype->size != 1 && cif->rtype->size != 2
&& cif->rtype->size != 4 && cif->rtype->size != 8))) {
- *rvalue = *(void **) argp;
- argp += sizeof(void *);
+ *rvalue = *(void **) cif->va.stack;
+ cif->va.stack += sizeof(void *);
}
#else
if ( cif->flags == FFI_TYPE_STRUCT
|| cif->flags == FFI_TYPE_MS_STRUCT ) {
- *rvalue = *(void **) argp;
- argp += sizeof(void *);
+ *rvalue = *(void **) cif->va.stack;
+ cif->va.stack += sizeof(void *);
}
#endif
- p_argv = avalue;
-
- for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
- {
- size_t z;
-
- /* Align if necessary */
- if ((sizeof(void*) - 1) & (size_t) argp) {
- argp = (char *) ALIGN(argp, sizeof(void*));
- }
+ /* Setup all fixed arguments. */
+ for (i = 0; i < cif->nargs; i++) {
+ ffi_closure_va_arg_internal(cif, cif->arg_types[i], &avalue[i], 0);
+ }
-#ifdef X86_WIN64
- if ((*p_arg)->size > sizeof(ffi_arg)
- || ((*p_arg)->type == FFI_TYPE_STRUCT
- && ((*p_arg)->size != 1 && (*p_arg)->size != 2
- && (*p_arg)->size != 4 && (*p_arg)->size != 8)))
- {
- z = sizeof(void *);
- *p_argv = *(void **)argp;
- }
- else
-#endif
- {
- z = (*p_arg)->size;
-
- /* because we're little endian, this is what it turns into. */
-
- *p_argv = (void*) argp;
- }
-
- p_argv++;
-#ifdef X86_WIN64
- argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
-#else
- argp += z;
-#endif
- }
-
+ /* In the closure, you can use ffi_closure_va_arg() to access varargs */
return;
}
diff --git a/native/libffi/src/x86/ffi64.c b/native/libffi/src/x86/ffi64.c
index 2014af2..58e5cf7 100644
--- a/native/libffi/src/x86/ffi64.c
+++ b/native/libffi/src/x86/ffi64.c
@@ -564,31 +564,98 @@ ffi_prep_closure_loc (ffi_closure* closure,
return FFI_OK;
}
+ffi_status
+ffi_closure_va_arg(ffi_cif *cif, ffi_type *va_type, void **va_value)
+{
+ enum x86_64_reg_class classes[MAX_CLASSES];
+ int n;
+ int ngpr = 0;
+ int nsse = 0;
+
+ n = examine_argument(va_type, classes, 0, &ngpr, &nsse);
+ if (n == 0
+ || cif->va.gprcount + ngpr > MAX_GPR_REGS
+ || cif->va.ssecount + nsse > MAX_SSE_REGS)
+ {
+ long align = va_type->alignment;
+
+ /* Stack arguments are *always* at least 8 byte aligned. */
+ if (align < 8)
+ align = 8;
+
+ /* Pass this argument in memory. */
+ cif->va.stack = (void *) ALIGN (cif->va.stack, align);
+ *va_value = cif->va.stack;
+ cif->va.stack += va_type->size;
+ }
+ /* If the argument is in a single register, or two consecutive
+ integer registers, then we can use that address directly. */
+ else if (n == 1
+ || (n == 2 && !(SSE_CLASS_P (classes[0])
+ || SSE_CLASS_P (classes[1]))))
+ {
+ /* The argument is in a single register. */
+ if (SSE_CLASS_P (classes[0]))
+ {
+ *va_value = &cif->va.reg_args->sse[cif->va.ssecount];
+ cif->va.ssecount += n;
+ }
+ else
+ {
+ *va_value = &cif->va.reg_args->gpr[cif->va.gprcount];
+ cif->va.gprcount += n;
+ }
+ }
+ /* Otherwise, allocate space to make them consecutive. */
+ else
+ {
+ char *a = alloca (16);
+ int j;
+
+ *va_value = a;
+ for (j = 0; j < n; j++, a += 8)
+ {
+ if (SSE_CLASS_P (classes[j]))
+ memcpy (a, &cif->va.reg_args->sse[cif->va.ssecount++], 8);
+ else
+ memcpy (a, &cif->va.reg_args->gpr[cif->va.gprcount++], 8);
+ }
+ }
+
+ return FFI_OK;
+}
+
int
ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue,
struct register_args *reg_args, char *argp)
{
ffi_cif *cif;
void **avalue;
- ffi_type **arg_types;
- long i, avn;
- int gprcount, ssecount, ngpr, nsse;
+ long i;
int ret;
cif = closure->cif;
avalue = alloca(cif->nargs * sizeof(void *));
- gprcount = ssecount = 0;
+ /* Setup the va */
+ cif->va.stack = argp;
+ cif->va.gprcount = 0;
+ cif->va.ssecount = 0;
+ cif->va.reg_args = reg_args;
+
+ /* Setup the return value */
ret = cif->rtype->type;
if (ret != FFI_TYPE_VOID)
{
enum x86_64_reg_class classes[MAX_CLASSES];
+ int ngpr = 0;
+ int nsse = 0;
int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
if (n == 0)
{
/* The return value goes in memory. Arrange for the closure
return value to go directly back to the original caller. */
- rvalue = (void *) (unsigned long) reg_args->gpr[gprcount++];
+ rvalue = (void *) (unsigned long) cif->va.reg_args->gpr[cif->va.gprcount++];
/* We don't have to do anything in asm for the return. */
ret = FFI_TYPE_VOID;
}
@@ -604,65 +671,11 @@ ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue,
}
}
- avn = cif->nargs;
- arg_types = cif->arg_types;
+ /* Setup all fixed arguments */
+ for (i = 0; i < cif->nargs; ++i) {
+ ffi_closure_va_arg(cif, cif->arg_types[i], &avalue[i]);
+ }
- for (i = 0; i < avn; ++i)
- {
- enum x86_64_reg_class classes[MAX_CLASSES];
- int n;
-
- n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
- if (n == 0
- || gprcount + ngpr > MAX_GPR_REGS
- || ssecount + nsse > MAX_SSE_REGS)
- {
- long align = arg_types[i]->alignment;
-
- /* Stack arguments are *always* at least 8 byte aligned. */
- if (align < 8)
- align = 8;
-
- /* Pass this argument in memory. */
- argp = (void *) ALIGN (argp, align);
- avalue[i] = argp;
- argp += arg_types[i]->size;
- }
- /* If the argument is in a single register, or two consecutive
- integer registers, then we can use that address directly. */
- else if (n == 1
- || (n == 2 && !(SSE_CLASS_P (classes[0])
- || SSE_CLASS_P (classes[1]))))
- {
- /* The argument is in a single register. */
- if (SSE_CLASS_P (classes[0]))
- {
- avalue[i] = ®_args->sse[ssecount];
- ssecount += n;
- }
- else
- {
- avalue[i] = ®_args->gpr[gprcount];
- gprcount += n;
- }
- }
- /* Otherwise, allocate space to make them consecutive. */
- else
- {
- char *a = alloca (16);
- int j;
-
- avalue[i] = a;
- for (j = 0; j < n; j++, a += 8)
- {
- if (SSE_CLASS_P (classes[j]))
- memcpy (a, ®_args->sse[ssecount++], 8);
- else
- memcpy (a, ®_args->gpr[gprcount++], 8);
- }
- }
- }
-
/* Invoke the closure. */
closure->fun (cif, rvalue, avalue, closure->user_data);
diff --git a/native/libffi/src/x86/ffitarget.h b/native/libffi/src/x86/ffitarget.h
index 46f294c..b3c9c3b 100644
--- a/native/libffi/src/x86/ffitarget.h
+++ b/native/libffi/src/x86/ffitarget.h
@@ -72,6 +72,27 @@ typedef signed long ffi_sarg;
#endif
#endif
+#define FFI_CLOSURE_VA_LIST 1
+
+#if FFI_CLOSURE_VA_LIST
+# if (defined (_WIN64) || defined (X86_WIN64)) || !defined (__x86_64__)
+typedef struct {
+ const char *stack;
+} ffi_closure_va_list;
+# else
+# if defined (__x86_64__) || defined (X86_64)
+typedef struct {
+ int gprcount;
+ int ssecount;
+ const char *stack;
+ struct register_args *reg_args;
+} ffi_closure_va_list;
+# else
+# error "Shouldn't be here for x86 or AMD64"
+# endif
+# endif
+#endif
+
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
diff --git a/native/libffi/src/x86/unix64.S b/native/libffi/src/x86/unix64.S
index dcd6bc7..899480a 100644
--- a/native/libffi/src/x86/unix64.S
+++ b/native/libffi/src/x86/unix64.S
@@ -219,7 +219,7 @@ ffi_closure_unix64:
movq %rcx, 24(%rsp)
movq %r8, 32(%rsp)
movq %r9, 40(%rsp)
- jc .Lsave_sse
+ jmp .Lsave_sse /* Unconditionally load SSE for varargs */
.Lret_from_save_sse:
movq %r10, %rdi
diff --git a/src/com/sun/jna/Native.java b/src/com/sun/jna/Native.java
index 7163c84..eb54422 100644
--- a/src/com/sun/jna/Native.java
+++ b/src/com/sun/jna/Native.java
@@ -1603,6 +1603,43 @@ public final class Native implements Version {
public static native long ffi_prep_closure(long cif, ffi_callback cb);
public static native void ffi_free_closure(long closure);
+ /** Expose FFI closure variadic calls. Exclude variable size aliases */
+ public static native byte ffi_closure_va_sint8(long cif);
+ public static native short ffi_closure_va_sint16(long cif);
+ public static native int ffi_closure_va_sint32(long cif);
+ public static native long ffi_closure_va_sint64(long cif);
+ public static native byte ffi_closure_va_uint8(long cif);
+ public static native char ffi_closure_va_uint16(long cif);
+ public static native int ffi_closure_va_uint32(long cif);
+ public static native long ffi_closure_va_uint64(long cif);
+ public static native float ffi_closure_va_float(long cif);
+ public static native double ffi_closure_va_double(long cif);
+
+ // These are private because we expose the version with objects
+ private static native long _ffi_closure_va_slong(long cif);
+ private static native long _ffi_closure_va_ulong(long cif);
+ private static native long _ffi_closure_va_pointer(long cif);
+
+ public static NativeLong ffi_closure_va_slong(long cif) {
+ return new NativeLong(_ffi_closure_va_slong(cif));
+ }
+ public static NativeLong ffi_closure_va_ulong(long cif) {
+ return new NativeLong(_ffi_closure_va_ulong(cif));
+ }
+ public static Pointer ffi_closure_va_pointer(long cif) {
+ long peer = _ffi_closure_va_pointer(cif);
+ return peer == 0 ? null : new Pointer(peer, cif);
+ }
+
+/* These may not work if the size doesn't match Java's
+ public static native byte ffi_closure_va_schar(long cif);
+ public static native short ffi_closure_va_sshort(long cif);
+ public static native int ffi_closure_va_sint(long cif);
+ public static native byte ffi_closure_va_uchar(long cif);
+ public static native short ffi_closure_va_ushort(long cif);
+ public static native int ffi_closure_va_uint(long cif);
+*/
+
/** Returns the size (calculated by libffi) of the given type. */
static native int initialize_ffi_type(long type_info);
diff --git a/src/com/sun/jna/Pointer.java b/src/com/sun/jna/Pointer.java
index 9f554cb..b7b25c5 100644
--- a/src/com/sun/jna/Pointer.java
+++ b/src/com/sun/jna/Pointer.java
@@ -64,7 +64,12 @@ public class Pointer {
*/
protected long peer;
- /** Derived class must assign peer pointer value. */
+ /** Pointer value of the real native ffi_cif pointer. Use long to be 64-bit safe.
+ * Should be used sparingly for variadic functions.
+ */
+ protected long cif = 0;
+
+ /** Derived class must assign peer and optionally cif pointer value. */
Pointer() { }
/** Create from native pointer. Don't use this unless you know what
@@ -74,6 +79,14 @@ public class Pointer {
this.peer = peer;
}
+ /** Create from native pointer. Don't use this unless you know what
+ * you're doing.
+ */
+ public Pointer(long peer, long cif) {
+ this.peer = peer;
+ this.cif = cif;
+ }
+
/** Provide a view of this memory using the given offset to calculate a new base address. */
public Pointer share(long offset) {
return share(offset, 0);
@@ -84,7 +97,7 @@ public class Pointer {
*/
public Pointer share(long offset, long sz) {
if (offset == 0) return this;
- return new Pointer(peer + offset);
+ return new Pointer(peer + offset, cif);
}
/** Zero memory for the given number of bytes. */
@@ -104,6 +117,7 @@ public class Pointer {
public boolean equals(Object o) {
if (o == this) return true;
if (o == null) return false;
+ // XXX not checking cif
return o instanceof Pointer && ((Pointer)o).peer == peer;
}
@@ -1304,6 +1318,11 @@ v * @param wide whether to convert from a wide or standard C string
p.peer = value;
}
+ /** Read the native peer value. Use with caution. */
+ public static long nativeCif(Pointer p) {
+ return p == null ? 0 : p.cif;
+ }
+
/** Pointer which disallows all read/write access. */
private static class Opaque extends Pointer {
private Opaque(long peer) { super(peer); }