[foreign] Pointer to fixed-size array: is jexctract's mapping to Java correct?
Jorn Vernee
jbvernee at xs4all.nl
Wed Feb 27 19:04:34 UTC 2019
I think the takeaway is that the conversion between array and pointer is
just less automatic in Java compared to C.
To go from a Pointer to an Array, you call `Pointer::withSize` and give
it an explicit size. Conversely you can decay an Array to a Pointer by
calling `Array::elementPointer`.
If I understand your requirements correctly, what you want is
`Array<Array<Double>>`, where the inner Array<Double> represents an
`fftw_complex`. E.g. (based on the example from the website):
```
// The canonical/internal type of fftw_complex
private static final LayoutType<Array<Double>> fftw_complex_t =
NativeTypes.DOUBLE.array(2); // an array of 2 doubles
// allocation helper
public static Array<Array<Double>> malloc_array(long n) {
return fftw_malloc(fftw_complex_t.bytesSize() *
n).cast(fftw_complex_t)
.withSize(n); // manually convert pointer type to
array type
}
public static void main(String[] args) {
long N = 1024;
Array<Array<Double>> in = malloc_array(N);
Array<Array<Double>> out = malloc_array(N);
Pointer<fftw_plan_s> p = fftw_plan_dft_1d(N,
// decay arrays to pointer (happens automatically in C)
in.elementPointer(),
out.elementPointer(),
FFTW_FORWARD,
FFTW_ESTIMATE
);
...
fftw_execute(p);
...
fftw_destroy_plan(p);
// again, decaying array to pointer
fftw_free(in.elementPointer());
fftw_free(out.elementPointer());
}
```
Where `in` and `out` are actually contiguous blocks of memory, just
viewed as 'array of array of 2 doubles'.
Jorn
Maurizio Cimadamore schreef op 2019-02-27 18:49:
> On 27/02/2019 16:14, Lev Serebryakov wrote:
>> Hmm. It is correct from point of view of type system, but it is
>> incorrect from point of view of memory layout, when it is translated
>> to
>> Java verbatim. "pointer to array" is something strange in plain C (see
>> comp.lang.c FAQ 6.12 about it: difference between array and pointer to
>> it is in type, but not in memory layout, as array is second-class
>> citizen in C). It is not pointer-to-pointer, it is equivalent (from
>> memory layout point of view) to array itself, and
>> Pointer<Array<Double>>
>> looks like double-indirection (if we remember, that Array is fancy
>> name
>> for Pointer in this case), which is not what this native API expected.
>
> Not sure I follow. A pointer to an array has a very different layout
> from an array.
>
> #include <stdio.h>
>
> typedef int ARR[5];
>
> int main(void) {
> printf("sizeof ARR = %d\n", sizeof(ARR));
> printf("sizeof ARR* = %d\n", sizeof(ARR*));
> return 0;
> }
>
>
> this prints:
>
> sizeof ARR = 20
> sizeof ARR* = 8
>
>
> As expected.
>
>
> What I think you are saying is, I believe, that if you have a
> Pointer<Array<X>> you can always flatten it as a Pointer<X>; while
> this is technically correct (the underlying layout is correct), when
> you do the flattening you completely lose track of the fact that the
> memory region is not just a sequence of X - but a sequence _of
> sequence_ of X.
>
> In your example, I agree that you might want to pass an array of 2048
> double to the function and be happy with it. But, what if you pass an
> array with only _one_ ? Or an array with an _odd_ number of doubles?
> This is allowed if we're just talking about a flattened double* - but,
> semantically speaking, this is NOT what the code says with the
> typedef.
>
> I tried to write examples along these lines:
>
> typedef double fftw_complex[2];
>
> int main(void) {
> double arr[100];
> fftw_complex *arg = arr;
> return 0;
> }
>
> And I always get some warnings when trying to pass a flattened double
> array as a pointer to double[].
>
> The code might work at runtime, assuming you are not misusing the API
> (see above, e.g. by passing an odd number of doubles), but this is
> still a potentially unsound operation.
>
> Maurizio
More information about the panama-dev
mailing list