Generic (void *)int

Jorn Vernee jbvernee at xs4all.nl
Mon Feb 18 11:38:51 UTC 2019


Maurizio Cimadamore schreef op 2019-02-18 12:24:
> Hi Giuseppe,
> To generalize Jorn's trick, you can write a generic method like this:
> 
> Pointer<?> makePointer(Scope sc, long value) {
>    return
> sc.allocate(NativeType.VOID).set(value).cast(NativeTypes.VOID).cast(NativeTypes.VOID.pointer()).get();
> 
> }
> 
> I think this does what you want.
> 
> As Jorn said, this is not 100% the same as in C code - as this will
> actually allocate a pointer to long, set the long to the desired
> value, then view it as pointer to pointer to void (so that the desired
> value will be used as an address).
> 
> 
> While an API can be added for this, we must also thread carefully -
> there's a balance here between allowing common C idioms and safety -
> if we make it too easy to create pointers to 'random' addresses, we
> also make it easy for people to shoot themselves in the foot.

I think this is mostly used to pass special values where a pointer is 
expected. The boxing code can handle the special values coming from 
native code already, so the hope is that there is a C API for retrieving 
a pointer with a special value in the library already.

Though, jextract can not handle all such cases yet. For instance, the 
Windows registry API uses these declaration for root registry keys:

#define HKEY_CLASSES_ROOT                   (( HKEY ) 
(ULONG_PTR)((LONG)0x80000000) )
#define HKEY_CURRENT_USER                   (( HKEY ) 
(ULONG_PTR)((LONG)0x80000001) )
#define HKEY_LOCAL_MACHINE                  (( HKEY ) 
(ULONG_PTR)((LONG)0x80000002) )
#define HKEY_USERS                          (( HKEY ) 
(ULONG_PTR)((LONG)0x80000003) )
#define HKEY_PERFORMANCE_DATA               (( HKEY ) 
(ULONG_PTR)((LONG)0x80000004) )
#define HKEY_PERFORMANCE_TEXT               (( HKEY ) 
(ULONG_PTR)((LONG)0x80000050) )
#define HKEY_PERFORMANCE_NLSTEXT            (( HKEY ) 
(ULONG_PTR)((LONG)0x80000060) )
#if (WINVER >= 0x0400)
#define HKEY_CURRENT_CONFIG                 (( HKEY ) 
(ULONG_PTR)((LONG)0x80000005) )
#define HKEY_DYN_DATA                       (( HKEY ) 
(ULONG_PTR)((LONG)0x80000006) )
#define HKEY_CURRENT_USER_LOCAL_SETTINGS    (( HKEY ) 
(ULONG_PTR)((LONG)0x80000007) )

But, these get omitted from the final binary, presumably since the value 
is not constant. (FWIW, a warning about that would be nice to have as 
well)

I think we can limit the damage if we add an API for creating pointers 
from literals, but don't make them dereferencable on the Java side, e.g. 
by using MemoryBoundInfo.NOTHING or References.OfGrumpy. Then users can 
only shoot themselves in the foot when passing the created pointer to a 
native function, which is already a foot-shooty situation any ways.

One of the questions is; to what Scope do these literals belong? Do we 
allow users to pass in a Scope? I think with the assumption that 
"pointer literals are just special values", it makes sense to have their 
Scope just be null, since no actual memory is managed.

Jorn

> Also, in terms of API evolution, we should refrain from thinking that
> pointer === address; there might be pointers (such as heap pointers)
> whose notion of 'address' is more blurry. An heap pointer expresses
> its address a pair of base Object + offset, so just creating a pointer
> out of thin air with a long won't work there.
> 
> Maurizio
> 
> 
> On 18/02/2019 09:56, Jorn Vernee wrote:
>> Hi Giuseppe,
>> 
>> You should be able to use this trick:
>> 
>>     long pointerValue = 12L; // e.g.
>>     Scope scope = Scope.newNativeScope; // or 
>> Scope.globalScope().fork() depending on which version you are
>>     Pointer<Long> ptr = scope.allocate(NativeTypes.UINT64);
>>     ptr.set(pointerValue);
>>     Pointer<?> result = 
>> ptr.cast(NativeTypes.VOID).cast(NativeTypes.VOID.pointer()).get();
>>     // use 'result'
>> 
>> Be aware that this does do an allocation of a 64 bit int, so you might 
>> want to reuse the allocated space if you create a lot of pointers from 
>> literals.
>> 
>> Maybe in the future we can add an API for creating pointers from long 
>> literals directly.
>> 
>> Jorn
>> 
>> Giuseppe Barbieri schreef op 2019-02-18 10:44:
>>> Thanks Sundar,
>>> 
>>> that works flawless for `(void *)0`
>>> 
>>> But now I also would need a generic solution, for example:
>>> 
>>> (void *)12
>>> 
>>> There is a sill opengl call ( glVertexPointer ) requesting 
>>> explicitely
>>> that: https://stackoverflow.com/a/8283855/1047713
>>> 
>>> Signature:
>>> 
>>> void glVertexAttribPointer(int index, int size, int type, byte
>>> normalized, int stride, Pointer<?> pointer);
>>> 
>>> 
>>> is there actually a way?
>>> 
>>> 
>>> 
>>> 
>>> 
>>> 
>>> You can use Pointer.nullPointer() method.
>>> 
>>> -Sundar
>>> 
>>> On 18/02/19, 8:09 AM, Giuseppe Barbieri wrote:
>>>> Hi,
>>>> 
>>>> I'm looking for a way to convert this:
>>>> 
>>>> (void*)0
>>>> 
>>>> in Java.
>>>> 
>>>> I tried to allocate a pointer and set its value to 0, but it didnt 
>>>> work
>>>> 
>>>> Any ideas, guys?
>>>> 
>>>> Thanks in advance


More information about the panama-dev mailing list