diff --git a/src/main/java/org/bytedeco/javacpp/BytePointer.java b/src/main/java/org/bytedeco/javacpp/BytePointer.java
index d722e6e2..aceeae54 100644
--- a/src/main/java/org/bytedeco/javacpp/BytePointer.java
+++ b/src/main/java/org/bytedeco/javacpp/BytePointer.java
@@ -163,7 +163,7 @@ public BytePointer() { }
 
     /** Returns the bytes, assuming a null-terminated string if {@code limit <= position}. */
     public byte[] getStringBytes() {
-        long size = limit - position;
+        long size = limit() - position();
         if (size <= 0) {
             size = strlen(this);
         }
diff --git a/src/main/java/org/bytedeco/javacpp/CharPointer.java b/src/main/java/org/bytedeco/javacpp/CharPointer.java
index f7c6cb97..365efd6a 100644
--- a/src/main/java/org/bytedeco/javacpp/CharPointer.java
+++ b/src/main/java/org/bytedeco/javacpp/CharPointer.java
@@ -129,8 +129,8 @@ public CharPointer() { }
 
     /** Returns the chars, assuming a null-terminated string if {@code limit <= position}. */
     public char[] getStringChars() {
-        if (limit > position) {
-            char[] array = new char[(int)Math.min(limit - position, Integer.MAX_VALUE)];
+        if (limit() > position()) {
+            char[] array = new char[(int)Math.min(limit() - position(), Integer.MAX_VALUE)];
             get(array);
             return array;
         }
diff --git a/src/main/java/org/bytedeco/javacpp/IntPointer.java b/src/main/java/org/bytedeco/javacpp/IntPointer.java
index b6bcd582..76ce3303 100644
--- a/src/main/java/org/bytedeco/javacpp/IntPointer.java
+++ b/src/main/java/org/bytedeco/javacpp/IntPointer.java
@@ -129,8 +129,8 @@ public IntPointer() { }
 
     /** Returns the code points, assuming a null-terminated string if {@code limit <= position}. */
     public int[] getStringCodePoints() {
-        if (limit > position) {
-            int[] array = new int[(int)Math.min(limit - position, Integer.MAX_VALUE)];
+        if (limit() > position()) {
+            int[] array = new int[(int)Math.min(limit() - position(), Integer.MAX_VALUE)];
             get(array);
             return array;
         }
diff --git a/src/main/java/org/bytedeco/javacpp/Pointer.java b/src/main/java/org/bytedeco/javacpp/Pointer.java
index b1d1f95e..869ed342 100644
--- a/src/main/java/org/bytedeco/javacpp/Pointer.java
+++ b/src/main/java/org/bytedeco/javacpp/Pointer.java
@@ -100,10 +100,11 @@ public Pointer(final Buffer b) {
             allocate(b);
         }
         if (!isNull()) {
-            address -= b.position() * sizeof();
-            position = b.position();
-            limit = b.limit();
-            capacity = b.capacity();
+            long s = sizeof();
+            position = b.position() * s;
+            address -= position;
+            limit = b.limit() * s;
+            capacity = b.capacity() * s;
             deallocator = new ProxyDeallocator(this, b);
         }
     }
@@ -113,7 +114,7 @@ public Pointer(final Buffer b) {
      * Called by native libraries to initialize the object fields.
      *
      * @param allocatedAddress the new address value of allocated native memory
-     * @param allocatedCapacity the amount of elements allocated (initial limit and capacity)
+     * @param allocatedCapacity the amount of bytes allocated (initial limit and capacity)
      * @param deallocatorAddress the pointer to the native deallocation function
      * @see NativeDeallocator
      */
@@ -129,7 +130,8 @@ void init(long allocatedAddress, long allocatedCapacity, long ownerAddress, long
 
     /** Adds {@code i * sizeof()} to {@link #address} and subtracts {@code i} from {@link #limit} and {@link #capacity}. */
     protected <P extends Pointer> P offsetAddress(long i) {
-        address += i * sizeof();
+        i *= sizeof();
+        address += i;
         limit = Math.max(0, limit - i);
         capacity = Math.max(0, capacity - i);
         return (P)this;
@@ -283,7 +285,7 @@ static class DeallocatorReference extends PhantomReference<Pointer> implements D
         DeallocatorReference(Pointer p, Deallocator deallocator) {
             super(p, referenceQueue);
             this.deallocator = deallocator;
-            this.bytes = p.capacity * p.sizeof();
+            this.bytes = p.capacity;
             this.count = new AtomicInteger(0);
         }
 
@@ -578,12 +580,12 @@ public static long maxPhysicalBytes() {
 
     /** The native address of this Pointer, which can be an array. */
     protected long address = 0;
-    /** The index of the element of a native array that should be accessed. */
-    protected long position = 0;
-    /** The index of the first element that should not be accessed, or 0 if unknown. */
-    protected long limit = 0;
-    /** The number of elements contained in this native array, or 0 if unknown. */
-    protected long capacity = 0;
+    /** The offset from address, in bytes, to the element of a native array that should be accessed. */
+    private long position = 0;
+    /** The offset from address, in bytes, that should not be accessed, or 0 if unknown. */
+    private long limit = 0;
+    /** The length of this native array, in bytes, or 0 if unknown. */
+    private long capacity = 0;
     /** The deallocator associated with this Pointer that should be called on garbage collection. */
     private Deallocator deallocator = null;
 
@@ -607,7 +609,7 @@ public long address() {
 
     /** Returns {@link #position}. */
     public long position() {
-        return position;
+        return position/sizeof();
     }
     /**
      * Sets the position and returns this. That makes the {@code array.position(i)}
@@ -617,13 +619,13 @@ public long position() {
      * @return this
      */
     public <P extends Pointer> P position(long position) {
-        this.position = position;
+        this.position = position * sizeof();
         return (P)this;
     }
 
     /** Returns {@link #limit}. */
     public long limit() {
-        return limit;
+        return limit/sizeof();
     }
     /**
      * Sets the limit and returns this.
@@ -633,13 +635,13 @@ public long limit() {
      * @return this
      */
     public <P extends Pointer> P limit(long limit) {
-        this.limit = limit;
+        this.limit = limit * sizeof();
         return (P)this;
     }
 
     /** Returns {@link #capacity}. */
     public long capacity() {
-        return capacity;
+        return capacity/sizeof();
     }
     /**
      * Sets the capacity and returns this.
@@ -649,8 +651,7 @@ public long capacity() {
      * @return this
      */
     public <P extends Pointer> P capacity(long capacity) {
-        this.limit = capacity;
-        this.capacity = capacity;
+        this.capacity = this.limit = capacity * sizeof();
         return (P)this;
     }
 
@@ -851,11 +852,10 @@ public ByteBuffer asByteBuffer() {
         if (limit > 0 && limit < position) {
             throw new IllegalArgumentException("limit < position: (" + limit + " < " + position + ")");
         }
-        int size = sizeof();
         Pointer p = new Pointer();
         p.address = address;
-        return p.position(size * position)
-                .capacity(size * (limit <= 0 ? position + 1 : limit))
+        return p.position(position)
+                .capacity(limit <= 0 ? position + 1 : limit)
                 .asDirectBuffer().order(ByteOrder.nativeOrder());
     }
     /**
@@ -922,14 +922,8 @@ public <P extends Pointer> P put(Pointer p) {
         if (p.limit > 0 && p.limit < p.position) {
             throw new IllegalArgumentException("limit < position: (" + p.limit + " < " + p.position + ")");
         }
-        int size = sizeof();
-        int psize = p.sizeof();
-        long length = psize * (p.limit <= 0 ? 1 : p.limit - p.position);
-        position *= size;
-        p.position *= psize;
+        long length = p.limit <= 0 ? 1 : p.limit - p.position;
         memcpy(this, p, length);
-        position /= size;
-        p.position /= psize;
         return (P)this;
     }
     /**
@@ -945,11 +939,8 @@ public <P extends Pointer> P fill(int b) {
         if (limit > 0 && limit < position) {
             throw new IllegalArgumentException("limit < position: (" + limit + " < " + position + ")");
         }
-        int size = sizeof();
-        long length = size * (limit <= 0 ? 1 : limit - position);
-        position *= size;
+        long length = limit <= 0 ? 1 : limit - position;
         memset(this, b, length);
-        position /= size;
         return (P)this;
     }
     /** Returns {@code fill(0)}. */
@@ -988,6 +979,6 @@ && getClass() != Pointer.class) {
      * {@link #position}, {@link #limit}, {@link #capacity}, and {@link #deallocator}. */
     @Override public String toString() {
         return getClass().getName() + "[address=0x" + Long.toHexString(address) +
-                ",position=" + position + ",limit=" + limit + ",capacity=" + capacity + ",deallocator=" + deallocator + "]";
+                ",position=" + position() + ",limit=" + limit() + ",capacity=" + capacity() + ",deallocator=" + deallocator + "]";
     }
 }
diff --git a/src/main/java/org/bytedeco/javacpp/tools/Generator.java b/src/main/java/org/bytedeco/javacpp/tools/Generator.java
index 0bb875e7..7d09ee73 100644
--- a/src/main/java/org/bytedeco/javacpp/tools/Generator.java
+++ b/src/main/java/org/bytedeco/javacpp/tools/Generator.java
@@ -405,6 +405,8 @@ boolean classes(boolean handleExceptions, boolean defineAdapters, boolean conver
         out.println("    #define JavaCPP_override");
         out.println("#endif");
         out.println();
+        out.println("#define JavaCPP_offsetBytes(ptr, o) ptr = (decltype(ptr)) ((char *)ptr + (o))");
+        out.println();
 
         if (loadSuffix == null) {
             loadSuffix = "";
@@ -926,11 +928,11 @@ boolean classes(boolean handleExceptions, boolean defineAdapters, boolean conver
         out.println("    }");
         out.println("}");
         out.println();
-        out.println("static JavaCPP_noinline void JavaCPP_initPointer(JNIEnv* env, jobject obj, const void* ptr, jlong size, void* owner, void (*deallocator)(void*)) {");
+        out.println("static JavaCPP_noinline void JavaCPP_initPointer(JNIEnv* env, jobject obj, const void* ptr, jlong sizeBytes, void* owner, void (*deallocator)(void*)) {");
         out.println("    if (owner != NULL && deallocator != NULL) {");
         out.println("        jvalue args[4];");
         out.println("        args[0].j = ptr_to_jlong(ptr);");
-        out.println("        args[1].j = size;");
+        out.println("        args[1].j = sizeBytes;");
         out.println("        args[2].j = ptr_to_jlong(owner);");
         out.println("        args[3].j = ptr_to_jlong(deallocator);");
         out.println("        if (JavaCPP_haveNonvirtual) {");
@@ -941,8 +943,8 @@ boolean classes(boolean handleExceptions, boolean defineAdapters, boolean conver
         out.println("        }");
         out.println("    } else {");
         out.println("        env->SetLongField(obj, JavaCPP_addressFID, ptr_to_jlong(ptr));");
-        out.println("        env->SetLongField(obj, JavaCPP_limitFID, (jlong)size);");
-        out.println("        env->SetLongField(obj, JavaCPP_capacityFID, (jlong)size);");
+        out.println("        env->SetLongField(obj, JavaCPP_limitFID, (jlong)sizeBytes);");
+        out.println("        env->SetLongField(obj, JavaCPP_capacityFID, (jlong)sizeBytes);");
         out.println("    }");
         out.println("}");
         out.println();
@@ -2082,12 +2084,12 @@ boolean methods(Class<?> cls) {
                     out.println("    }");
                 }
                 if (!cls.isAnnotationPresent(Opaque.class)) {
-                    out.println("    jlong position = env->GetLongField(obj, JavaCPP_positionFID);");
+                    out.println("    jlong positionBytes = env->GetLongField(obj, JavaCPP_positionFID);");
                     if (methodInfo.bufferGetter) {
-                        out.println("    jlong limit = env->GetLongField(obj, JavaCPP_limitFID);");
-                        out.println("    jlong capacity = env->GetLongField(obj, JavaCPP_capacityFID);");
+                        out.println("    jlong limitBytes = env->GetLongField(obj, JavaCPP_limitFID);");
+                        out.println("    jlong capacityBytes = env->GetLongField(obj, JavaCPP_capacityFID);");
                     } else {
-                        out.println("    ptr += position;");
+                        out.println("    JavaCPP_offsetBytes(ptr, positionBytes);");
                     }
                 }
             }
@@ -2176,23 +2178,23 @@ void parametersBefore(MethodInformation methodInfo) {
                         out.println("    }");
                     }
                     if (adapterInfo != null || prevAdapterInfo != null) {
-                        out.println("    jlong size" + j + " = arg" + j + " == NULL ? 0 : env->GetLongField(arg" + j +
+                        out.println("    jlong sizeBytes" + j + " = arg" + j + " == NULL ? 0 : env->GetLongField(arg" + j +
                                 ", JavaCPP_limitFID);");
                         out.println("    void* owner" + j + " = JavaCPP_getPointerOwner(env, arg" + j + ");");
                     }
                     if (!methodInfo.parameterTypes[j].isAnnotationPresent(Opaque.class)) {
-                        out.println("    jlong position" + j + " = arg" + j + " == NULL ? 0 : env->GetLongField(arg" + j +
+                        out.println("    jlong positionBytes" + j + " = arg" + j + " == NULL ? 0 : env->GetLongField(arg" + j +
                                 ", JavaCPP_positionFID);");
-                        out.println("    ptr"  + j + " += position" + j + ";");
+                        out.println("    JavaCPP_offsetBytes(ptr"  + j + ", positionBytes" + j + ");");
                         if (adapterInfo != null || prevAdapterInfo != null) {
-                            out.println("    size" + j + " -= position" + j + ";");
+                            out.println("    sizeBytes" + j + " -= positionBytes" + j + ";");
                         }
                     }
                 } else if (methodInfo.parameterTypes[j] == String.class) {
                     passesStrings = true;
                     out.println(getStringData("arg" + j, methodInfo.parameterAnnotations[j]));
                     if (adapterInfo != null || prevAdapterInfo != null) {
-                        out.println("    jlong size" + j + " = 0;");
+                        out.println("    jlong sizeBytes" + j + " = 0;");
                         out.println("    void* owner" + j + " = (void*)ptr" + j + ";");
                     }
                 } else if (methodInfo.parameterTypes[j].isArray() &&
@@ -2203,18 +2205,18 @@ void parametersBefore(MethodInformation methodInfo) {
                             methodInfo.memberGetter || methodInfo.memberSetter) {
                         out.println("(j" + s + "*)env->GetPrimitiveArrayCritical(arg" + j + ", NULL);");
                     } else {
-                        s = Character.toUpperCase(s.charAt(0)) + s.substring(1);
-                        out.println("env->Get" + s + "ArrayElements(arg" + j + ", NULL);");
+                        String S = Character.toUpperCase(s.charAt(0)) + s.substring(1);
+                        out.println("env->Get" + S + "ArrayElements(arg" + j + ", NULL);");
                     }
                     if (adapterInfo != null || prevAdapterInfo != null) {
-                        out.println("    jlong size" + j +
-                                " = arg" + j + " == NULL ? 0 : env->GetArrayLength(arg" + j + ");");
+                        out.println("    jlong sizeBytes" + j +
+                                " = arg" + j + " == NULL ? 0 : sizeof(j" + s + ") * env->GetArrayLength(arg" + j + ");");
                         out.println("    void* owner" + j + " = (void*)ptr" + j + ";");
                     }
                 } else if (Buffer.class.isAssignableFrom(methodInfo.parameterTypes[j])) {
                     out.println("arg" + j + " == NULL ? NULL : (" + typeName[0] + typeName[1] + ")env->GetDirectBufferAddress(arg" + j + ");");
                     if (adapterInfo != null || prevAdapterInfo != null) {
-                        out.println("    jlong size" + j + " = arg" + j + " == NULL ? 0 : env->GetIntField(arg" + j +
+                        out.println("    jlong sizeBytes" + j + " = arg" + j + " == NULL ? 0 : sizeof(*ptr" + j + ") *env->GetIntField(arg" + j +
                                 ", JavaCPP_bufferLimitFID);");
                         out.println("    void* owner" + j + " = (void*)ptr" + j + ";");
                     }
@@ -2241,11 +2243,11 @@ void parametersBefore(MethodInformation methodInfo) {
                         out.println("        }");
                         out.println("    }");
                     }
-                    out.println("    jlong position" + j + " = arg" + j + " == NULL ? 0 : env->GetIntField(arg" + j +
+                    out.println("    jlong positionElements" + j + " = arg" + j + " == NULL ? 0 : env->GetIntField(arg" + j +
                             ", JavaCPP_bufferPositionFID);");
-                    out.println("    ptr"  + j + " += position" + j + ";");
+                    out.println("    ptr"  + j + " += positionElements" + j + ";");
                     if (adapterInfo != null || prevAdapterInfo != null) {
-                        out.println("    size" + j + " -= position" + j + ";");
+                        out.println("    sizeBytes" + j + " -= sizeof(*ptr" + j + ") * positionElements" + j + ";");
                     }
                 } else {
                     out.println("arg" + j + ";");
@@ -2263,7 +2265,7 @@ void parametersBefore(MethodInformation methodInfo) {
                         // sometimes we need to use the Cast annotation for declaring functions only
                         adapterLine += cast;
                     }
-                    adapterLine += "ptr" + j + ", size" + j + ", owner" + j;
+                    adapterLine += "ptr" + j + ", sizeBytes" + j + "/sizeof(*ptr" + j + "), owner" + j;
                     if (--prevAdapterInfo.argc > 0) {
                         adapterLine += ", ";
                     }
@@ -2692,11 +2694,14 @@ void returnAfter(MethodInformation methodInfo) {
 
         if (methodInfo.returnType == void.class) {
             if (methodInfo.allocator || methodInfo.arrayAllocator) {
-                out.println(indent + "jlong rcapacity = " + (methodInfo.arrayAllocator ? "arg0;" : "1;"));
+                // HG : this is probably wrong:
+                String sizeof = methodInfo.cls == Pointer.class ? "sizeof(*ptr0)" : "sizeof(*rptr)";
+                out.println(indent + "jlong rcapacityBytes = " +
+                    (methodInfo.arrayAllocator ? "arg0 * " + sizeof : sizeof) + ";");
                 boolean noDeallocator = methodInfo.cls == Pointer.class ||
                         methodInfo.cls.isAnnotationPresent(NoDeallocator.class) ||
                         methodInfo.method.isAnnotationPresent(NoDeallocator.class);
-                out.print(indent + "JavaCPP_initPointer(env, obj, rptr, rcapacity, rptr, ");
+                out.print(indent + "JavaCPP_initPointer(env, obj, rptr, rcapacityBytes, rptr, ");
                 if (noDeallocator) {
                     out.println("NULL);");
                 } else if (methodInfo.arrayAllocator) {
@@ -2734,7 +2739,7 @@ void returnAfter(MethodInformation methodInfo) {
                 if (adapterInfo != null) {
                     out.println(indent + "rptr = radapter;");
                     if (methodInfo.returnType != String.class) {
-                        out.println(indent + "jlong rcapacity = (jlong)radapter.size;");
+                        out.println(indent + "jlong rcapacityElements = (jlong)radapter.size;");
                         if (Pointer.class.isAssignableFrom(methodInfo.returnType)) {
                             out.println(indent + "void* rowner = radapter.owner;");
                             out.println(indent + "void (*deallocator)(void*) = rowner != NULL ? &" + adapterInfo.name + "::deallocate : 0;");
@@ -2745,7 +2750,7 @@ void returnAfter(MethodInformation methodInfo) {
                     needInit = true;
                 } else if (returnBy instanceof ByVal ||
                         FunctionPointer.class.isAssignableFrom(methodInfo.returnType)) {
-                    out.println(indent + "jlong rcapacity = 1;");
+                    out.println(indent + "jlong rcapacityElements = 1;");
                     out.println(indent + "void* rowner = (void*)rptr;");
                     out.println(indent + "void (*deallocator)(void*) = &JavaCPP_" +
                             mangle(methodInfo.returnType.getName()) + "_deallocate;");
@@ -2779,7 +2784,7 @@ void returnAfter(MethodInformation methodInfo) {
                             (methodInfo.parameterTypes.length > 0 && methodInfo.parameterTypes[0] == Class.class ? ", arg0);" : ");"));
                     out.println(indent + "    if (rarg != NULL) {");
                     if (needInit) {
-                        out.println(indent + "        JavaCPP_initPointer(env, rarg, rptr, rcapacity, rowner, deallocator);");
+                        out.println(indent + "        JavaCPP_initPointer(env, rarg, rptr, rcapacityElements * sizeof(*rptr), rowner, deallocator);");
                     } else {
                         out.println(indent + "        env->SetLongField(rarg, JavaCPP_addressFID, ptr_to_jlong(rptr));");
                     }
@@ -2793,13 +2798,13 @@ void returnAfter(MethodInformation methodInfo) {
                 } else if (methodInfo.returnType.isArray() &&
                         methodInfo.returnType.getComponentType().isPrimitive()) {
                     if (adapterInfo == null && !(returnBy instanceof ByVal)) {
-                        out.println(indent + "jlong rcapacity = rptr != NULL ? 1 : 0;");
+                        out.println(indent + "jlong rcapacityElements = rptr != NULL ? 1 : 0;");
                     }
                     String componentName = methodInfo.returnType.getComponentType().getName();
                     String componentNameUpperCase = Character.toUpperCase(componentName.charAt(0)) + componentName.substring(1);
                     out.println(indent + "if (rptr != NULL) {");
-                    out.println(indent + "    rarg = env->New" + componentNameUpperCase + "Array(rcapacity < INT_MAX ? rcapacity : INT_MAX);");
-                    out.println(indent + "    env->Set" + componentNameUpperCase + "ArrayRegion(rarg, 0, rcapacity < INT_MAX ? rcapacity : INT_MAX, (j" + componentName + "*)rptr);");
+                    out.println(indent + "    rarg = env->New" + componentNameUpperCase + "Array(rcapacityElements < INT_MAX ? rcapacityElements : INT_MAX);");
+                    out.println(indent + "    env->Set" + componentNameUpperCase + "ArrayRegion(rarg, 0, rcapacityElements < INT_MAX ? rcapacityElements : INT_MAX, (j" + componentName + "*)rptr);");
                     out.println(indent + "}");
                     if (adapterInfo != null) {
                         out.println(indent + "if (deallocator != 0 && rptr != NULL) {");
@@ -2808,20 +2813,19 @@ void returnAfter(MethodInformation methodInfo) {
                     }
                 } else if (Buffer.class.isAssignableFrom(methodInfo.returnType)) {
                     if (methodInfo.bufferGetter) {
-                        out.println(indent + "jlong rposition = position;");
-                        out.println(indent + "jlong rlimit = limit;");
-                        out.println(indent + "jlong rcapacity = capacity;");
+                        out.println(indent + "jlong rpositionBytes = positionBytes;");
+                        out.println(indent + "jlong rlimitBytes = limitBytes;");
+                        out.println(indent + "jlong rcapacityBytes = capacityBytes;");
                     } else if (adapterInfo == null && !(returnBy instanceof ByVal)) {
-                        out.println(indent + "jlong rcapacity = rptr != NULL ? 1 : 0;");
+                        out.println(indent + "jlong rcapacityBytes = rptr != NULL ? sizeof(*rptr) : 0;");
+                    } else {
+                        out.println(indent + "jlong rcapacityBytes = rptr == NULL ? 0 : rcapacityElements * sizeof(*rptr);");
                     }
                     out.println(indent + "if (rptr != NULL) {");
-                    out.println(indent + "    jlong rcapacityptr = rcapacity * sizeof(rptr[0]);");
-                    out.println(indent + "    rarg = env->NewDirectByteBuffer((void*)rptr, rcapacityptr < INT_MAX ? rcapacityptr : INT_MAX);");
+                    out.println(indent + "    rarg = env->NewDirectByteBuffer((void*)rptr, rcapacityBytes < INT_MAX ? rcapacityBytes : INT_MAX);");
                     if (methodInfo.bufferGetter) {
-                        out.println(indent + "    jlong rpositionptr = rposition * sizeof(rptr[0]);");
-                        out.println(indent + "    jlong rlimitptr = rlimit * sizeof(rptr[0]);");
-                        out.println(indent + "    env->SetIntField(rarg, JavaCPP_bufferPositionFID, rpositionptr < INT_MAX ? rpositionptr : INT_MAX);");
-                        out.println(indent + "    env->SetIntField(rarg, JavaCPP_bufferLimitFID, rlimitptr < INT_MAX ? rlimitptr : INT_MAX);");
+                        out.println(indent + "    env->SetIntField(rarg, JavaCPP_bufferPositionFID, rpositionBytes < INT_MAX ? rpositionBytes : INT_MAX);");
+                        out.println(indent + "    env->SetIntField(rarg, JavaCPP_bufferLimitFID, rlimitBytes < INT_MAX ? rlimitBytes : INT_MAX);");
                     }
                     out.println(indent + "}");
                 }
@@ -2862,19 +2866,20 @@ void parametersAfter(MethodInformation methodInfo) {
                 if (adapterInfo != null) {
                     for (int k = 0; k < adapterInfo.argc; k++) {
                         out.println("    " + typeName[0] + " rptr" + (j+k) + typeName[1] + " = " + cast + "adapter" + j + ";");
-                        out.println("    jlong rsize" + (j+k) + " = (jlong)adapter" + j + ".size" + (k > 0 ? (k+1) + ";" : ";"));
+                        // HG: I don't understand this j/k double loop. Please check the sizeof.
+                        out.println("    jlong rsizeBytes" + (j+k) + " = sizeof(*ptr" + j + ") * (jlong)adapter" + j + ".size" + (k > 0 ? (k+1) + ";" : ";"));
                         out.println("    void* rowner" + (j+k) + " = adapter" + j + ".owner" + (k > 0 ? (k+1) + ";" : ";"));
                         out.println("    if (rptr" + (j+k) + " != " + cast + "ptr" + (j+k) + ") {");
-                        out.println("        JavaCPP_initPointer(env, arg" + j + ", rptr" + (j+k) + ", rsize" + (j+k) + ", rowner" + (j+k) + ", &" + adapterInfo.name + "::deallocate);");
+                        out.println("        JavaCPP_initPointer(env, arg" + j + ", rptr" + (j+k) + ", rsizeBytes" + (j+k) + ", rowner" + (j+k) + ", &" + adapterInfo.name + "::deallocate);");
                         out.println("    } else {");
-                        out.println("        env->SetLongField(arg" + j + ", JavaCPP_limitFID, rsize" + (j+k)
-                                + (!methodInfo.parameterTypes[j].isAnnotationPresent(Opaque.class) ? " + position" + (j+k) : "") + ");");
+                        out.println("        env->SetLongField(arg" + j + ", JavaCPP_limitFID, rsizeBytes" + (j+k)
+                                + (!methodInfo.parameterTypes[j].isAnnotationPresent(Opaque.class) ? " + positionBytes" + (j+k) : "") + ");");
                         out.println("    }");
                     }
                 } else if ((passBy instanceof ByPtrPtr || passBy instanceof ByPtrRef) &&
                         !methodInfo.valueSetter && !methodInfo.memberSetter) {
                     if (!methodInfo.parameterTypes[j].isAnnotationPresent(Opaque.class)) {
-                        out.println("    ptr" + j + " -= position" + j + ";");
+                        out.println("    JavaCPP_offsetBytes(ptr" + j + ", -positionBytes" + j + ");");
                     }
                     out.println("    if (arg" + j + " != NULL) env->SetLongField(arg" + j +
                             ", JavaCPP_addressFID, ptr_to_jlong(ptr" + j + "));");
@@ -2913,10 +2918,10 @@ void parametersAfter(MethodInformation methodInfo) {
                 parameterSimpleName = parameterSimpleName.substring(0, parameterSimpleName.length() - 6);
                 String parameterSimpleNameLowerCase = Character.toLowerCase(parameterSimpleName.charAt(0)) + parameterSimpleName.substring(1);
                 if (methodInfo.criticalRegion) {
-                    out.println("env->ReleasePrimitiveArrayCritical(arr" + j + ", ptr" + j + " - position" + j +", " + releaseArrayFlag + ");");
+                    out.println("env->ReleasePrimitiveArrayCritical(arr" + j + ", ptr" + j + " - positionElements" + j +", " + releaseArrayFlag + ");");
                 } else {
                     out.println("env->Release" + parameterSimpleName + "ArrayElements(arr" + j + ", " +
-                                "(j" + parameterSimpleNameLowerCase + "*)(ptr" + j + " - position" + j +"), " +
+                                "(j" + parameterSimpleNameLowerCase + "*)(ptr" + j + " - positionElements" + j +"), " +
                                 releaseArrayFlag + ");");
                 }
             }
@@ -3150,14 +3155,14 @@ void callback(Class<?> cls, Method callbackMethod, String callbackName, int allo
                     boolean needInit = false;
                     if (adapterInfo != null) {
                         if (callbackParameterTypes[j] != String.class) {
-                            out.println("    jlong size" + j + " = (jlong)adapter" + j + ".size;");
+                            out.println("    jlong sizeBytes" + j + " = sizeof(*ptr" + j + ") * (jlong)adapter" + j + ".size;");
                             out.println("    void* owner" + j + " = adapter" + j + ".owner;");
                             out.println("    void (*deallocator" + j + ")(void*) = &" + adapterInfo.name + "::deallocate;");
                         }
                         needInit = true;
                     } else if ((passBy instanceof ByVal && callbackParameterTypes[j] != Pointer.class) ||
                             FunctionPointer.class.isAssignableFrom(callbackParameterTypes[j])) {
-                        out.println("    jlong size" + j + " = 1;");
+                        out.println("    jlong sizeBytes" + j + " = sizeof(*ptr" + j + ");");
                         out.println("    void* owner" + j + " = ptr" + j + ";");
                         out.println("    void (*deallocator" + j + ")(void*) = &JavaCPP_" +
                                 mangle(callbackParameterTypes[j].getName()) + "_deallocate;");
@@ -3177,7 +3182,7 @@ void callback(Class<?> cls, Method callbackMethod, String callbackName, int allo
                         }
                         out.println("    if (obj" + j + " != NULL) { ");
                         if (needInit) {
-                            out.println("        JavaCPP_initPointer(env, obj" + j + ", ptr" + j + ", size" + j + ", owner" + j + ", deallocator" + j + ");");
+                            out.println("        JavaCPP_initPointer(env, obj" + j + ", ptr" + j + ", sizeBytes" + j + ", owner" + j + ", deallocator" + j + ");");
                         } else {
                             out.println("        env->SetLongField(obj" + j + ", JavaCPP_addressFID, ptr_to_jlong(ptr" + j + "));");
                         }
@@ -3201,13 +3206,13 @@ void callback(Class<?> cls, Method callbackMethod, String callbackName, int allo
                     } else if (callbackParameterTypes[j].isArray() &&
                             callbackParameterTypes[j].getComponentType().isPrimitive()) {
                         if (adapterInfo == null) {
-                            out.println("    jlong size" + j + " = ptr" + j + " != NULL ? 1 : 0;");
+                            out.println("    jlong sizeElements" + j + " = ptr" + j + " != NULL ? 1 : 0;");
                         }
                         String componentType = callbackParameterTypes[j].getComponentType().getName();
                         String S = Character.toUpperCase(componentType.charAt(0)) + componentType.substring(1);
                         out.println("    if (ptr" + j + " != NULL) {");
-                        out.println("        obj" + j + " = env->New" + S + "Array(size" + j + " < INT_MAX ? size" + j + " : INT_MAX);");
-                        out.println("        env->Set" + S + "ArrayRegion(obj" + j + ", 0, size" + j + " < INT_MAX ? size" + j + " : INT_MAX, (j" + componentType + "*)ptr" + j + ");");
+                        out.println("        obj" + j + " = env->New" + S + "Array(sizeElements" + j + " < INT_MAX ? sizeElements" + j + " : INT_MAX);");
+                        out.println("        env->Set" + S + "ArrayRegion(obj" + j + ", 0, sizeElements" + j + " < INT_MAX ? sizeElements" + j + " : INT_MAX, (j" + componentType + "*)ptr" + j + ");");
                         out.println("    }");
                         if (adapterInfo != null) {
                             out.println("    if (deallocator" + j + " != 0 && ptr" + j + " != NULL) {");
@@ -3217,11 +3222,11 @@ void callback(Class<?> cls, Method callbackMethod, String callbackName, int allo
                         out.println("    args[" + j + "].l = obj" + j + ";");
                     } else if (Buffer.class.isAssignableFrom(callbackParameterTypes[j])) {
                         if (adapterInfo == null) {
-                            out.println("    jlong size" + j + " = ptr" + j + " != NULL ? 1 : 0;");
+                            out.println("    jlong sizeElements" + j + " = ptr" + j + " != NULL ? 1 : 0;");
                         }
                         out.println("    if (ptr" + j + " != NULL) {");
-                        out.println("        jlong sizeptr = size" + j + " * sizeof(ptr" + j + "[0]);");
-                        out.println("        obj" + j + " = env->NewDirectByteBuffer((void*)ptr" + j + ", sizeptr < INT_MAX ? sizeptr : INT_MAX);");
+                        out.println("        jlong sizeBytes = sizeElements" + j + " * sizeof(ptr" + j + "[0]);");
+                        out.println("        obj" + j + " = env->NewDirectByteBuffer((void*)ptr" + j + ", sizeBytes < INT_MAX ? sizeBytes : INT_MAX);");
                         out.println("    }");
                         out.println("    args[" + j + "].l = obj" + j + ";");
                     } else {
@@ -3292,18 +3297,18 @@ void callback(Class<?> cls, Method callbackMethod, String callbackName, int allo
                     out.println("    " + typeName[0] + " rptr" + j + typeName[1] + " = (" +
                             typeName[0] + typeName[1] + ")jlong_to_ptr(env->GetLongField(obj" + j + ", JavaCPP_addressFID));");
                     if (adapterInfo != null) {
-                        out.println("    jlong rsize" + j + " = env->GetLongField(obj" + j + ", JavaCPP_limitFID);");
+                        out.println("    jlong rsizeBytes" + j + " = env->GetLongField(obj" + j + ", JavaCPP_limitFID);");
                         out.println("    void* rowner" + j + " = JavaCPP_getPointerOwner(env, obj" + j + ");");
                     }
                     if (!callbackParameterTypes[j].isAnnotationPresent(Opaque.class) && !FunctionPointer.class.isAssignableFrom(callbackParameterTypes[j])) {
-                        out.println("    jlong rposition" + j + " = env->GetLongField(obj" + j + ", JavaCPP_positionFID);");
-                        out.println("    rptr" + j + " += rposition" + j + ";");
+                        out.println("    jlong rpositionBytes" + j + " = env->GetLongField(obj" + j + ", JavaCPP_positionFID);");
+                        out.println("    JavaCPP_offsetBytes(rptr" + j + ", rpositionBytes" + j + ");");
                         if (adapterInfo != null) {
-                            out.println("    rsize" + j + " -= rposition" + j + ";");
+                            out.println("    rsizeBytes" + j + " -= rpositionBytes" + j + ";");
                         }
                     }
                     if (adapterInfo != null) {
-                        out.println("    adapter" + j + ".assign(rptr" + j + ", rsize" + j + ", rowner" + j + ");");
+                        out.println("    adapter" + j + ".assign(rptr" + j + ", rsizeElements" + j + ", rowner" + j + ");");
                     } else if (passBy instanceof ByPtrPtr) {
                         out.println("    if (arg" + j + " != NULL) {");
                         out.println("        *arg" + j + " = *" + cast + "&rptr" + j + ";");
@@ -3344,32 +3349,34 @@ void callback(Class<?> cls, Method callbackMethod, String callbackName, int allo
                 out.println("    " + returnTypeName[0] + " rptr" + returnTypeName[1] + " = rarg == NULL ? NULL : (" +
                         returnTypeName[0] + returnTypeName[1] + ")jlong_to_ptr(env->GetLongField(rarg, JavaCPP_addressFID));");
                 if (returnAdapterInfo != null) {
-                    out.println("    jlong rsize = rarg == NULL ? 0 : env->GetLongField(rarg, JavaCPP_limitFID);");
+                    out.println("    jlong rsizeBytes = rarg == NULL ? 0 : env->GetLongField(rarg, JavaCPP_limitFID);");
+                    out.println("    jlong rsizeElements = rsizeBytes / sizeof(*rarg);");
                     out.println("    void* rowner = JavaCPP_getPointerOwner(env, rarg);");
                 }
                 if (!callbackReturnType.isAnnotationPresent(Opaque.class)) {
-                    out.println("    jlong rposition = rarg == NULL ? 0 : env->GetLongField(rarg, JavaCPP_positionFID);");
-                    out.println("    rptr += rposition;");
+                    out.println("    jlong rpositionBytes = rarg == NULL ? 0 : env->GetLongField(rarg, JavaCPP_positionFID);");
+                    out.println("    JavaCPP_offsetBytes(rptr, rpositionBytes);");
                     if (returnAdapterInfo != null) {
-                        out.println("    rsize -= rposition;");
+                        out.println("    rsizeBytes -= rpositionBytes;");
                     }
                 }
             } else if (callbackReturnType == String.class) {
                 passesStrings = true;
                 out.println("    " + returnTypeName[0] + " rptr" + returnTypeName[1] + " = " + getStringData("rarg", callbackAnnotations));
                 if (returnAdapterInfo != null) {
-                    out.println("    jlong rsize = 0;");
+                    out.println("    jlong rsizeBytes = 0;");
                     out.println("    void* rowner = (void*)rptr;");
                 }
             } else if (Buffer.class.isAssignableFrom(callbackReturnType)) {
                 out.println("    " + returnTypeName[0] + " rptr" + returnTypeName[1] + " = rarg == NULL ? NULL : ("
                         + returnTypeName[0] + returnTypeName[1] + ")env->GetDirectBufferAddress(rarg);");
                 if (returnAdapterInfo != null) {
-                    out.println("    jlong rsize = rarg == NULL ? 0 : env->GetIntField(rarg, JavaCPP_bufferLimitFID);");
+                    out.println("    jlong rsizeElements = rarg == NULL ? 0 : env->GetIntField(rarg, JavaCPP_bufferLimitFID);");
                     out.println("    void* rowner = (void*)rptr;");
-                    out.println("    jlong rposition = rarg == NULL ? 0 : env->GetIntField(rarg, JavaCPP_bufferPositionFID);");
-                    out.println("    rptr += rposition;");
-                    out.println("    rsize -= rposition;");
+                    out.println("    jlong rpositionElements = rarg == NULL ? 0 : env->GetIntField(rarg, JavaCPP_bufferPositionFID);");
+                    out.println("    rptr += rpositionElements;");
+                    out.println("    rsizeElements -= rpositionElements;");
+                    out.println("    jlong rsizeBytes = rsizeElements * sizeof(*rptr)");
                 }
             } else if (!callbackReturnType.isPrimitive()) {
                 logger.warn("Callback \"" + callbackMethod + "\" has unsupported return type \"" +
@@ -3402,7 +3409,7 @@ void callback(Class<?> cls, Method callbackMethod, String callbackName, int allo
                 out.println("    return " + callbackReturnCast + "rval;");
             } else if (returnAdapterInfo != null) {
                 usesAdapters = true;
-                out.println("    return " + returnAdapterInfo.name + "(" + callbackReturnCast + "rptr, rsize, rowner);");
+                out.println("    return " + returnAdapterInfo.name + "(" + callbackReturnCast + "rptr, rsizeBytes/sizeof(*rptr), rowner);");
             } else if (FunctionPointer.class.isAssignableFrom(callbackReturnType)) {
                 functions.index(callbackReturnType);
                 out.println("    return " + callbackReturnCast + "(rptr == NULL ? NULL : rptr->ptr);");
@@ -3435,7 +3442,7 @@ void callbackAllocator(Class<?> cls, String callbackName, int allocatorMax) {
         out.println("    " + instanceTypeName + "* rptr = new (std::nothrow) " + instanceTypeName + ";");
         out.println("    if (rptr != NULL) {");
         out.println("        rptr->obj = obj;");
-        out.println("        JavaCPP_initPointer(env, obj, rptr, 1, rptr, &JavaCPP_" + mangle(cls.getName()) + "_deallocate);");
+        out.println("        JavaCPP_initPointer(env, obj, rptr, sizeof(*rptr), rptr, &JavaCPP_" + mangle(cls.getName()) + "_deallocate);");
         deallocators.index(cls);
         if (callbackName != null) {
             out.println("        for (int i = 0; i < " + allocatorMax + "; i++) {");