8 messages in net.java.dev.jna.usersRe: [jna-users] getting at a structur...
FromSent OnAttachments
Paul LoyJan 23, 2008 10:34 am 
Timothy WallJan 23, 2008 11:04 am 
Paul LoyJan 24, 2008 5:29 am 
Paul LoyJan 24, 2008 5:30 am 
Timothy WallJan 24, 2008 5:38 am 
Paul LoyJan 25, 2008 5:24 am 
Timothy WallJan 25, 2008 5:58 am 
Paul LoyJan 25, 2008 6:50 am 
Actions with this message:
Paste this link in email or IM:
Paste this link in email or IM:
Atom feed for this thread
Paste this URL into your reader:
Subject:Re: [jna-users] getting at a structure with unknown structure sizeActions...
From:Paul Loy (pa@keteracel.com)
Date:Jan 25, 2008 5:24:11 am
List:net.java.dev.jna.users

Hi Tim,

unfortunately, I can't use NewHandle as it's not available on windows (I need it to work on Windows and Mac). I've been able to work around it by staying in QTJ to get the SampleDescription, then by getting the SoundDescription.version, I create a memory that will hold a pointer. I then set an int on the memory to the ID of the QTJ Sample Description, then I can read the applicable piece of memory to get the relevant info out:

if (audioDescription.getVersion() == 2) { Memory soundDescriptionHandle = new Memory(Pointer.SIZE); soundDescriptionHandle.setInt(0, QTObject.ID (audioDescription));

numchannels = soundDescriptionHandle.getPointer(0).getPointer(0)

.getInt(kNumChannelsSoundDescriptionV2Index); }

What would be good would be to have a Structure.getRelativeFieldAddress(String fieldName, Class<? extends Structure> structureType). This would mean that instead of me having to use a calculator and scratch my head to get the kNumChannelsSoundDescriptionV2Index value, I could just call Structure.getRelativeFieldAddress("numChannels", SoundDescriptionV2.class);

I wrote a rough cut to test it out but I guess you already have code to get at the relative field address (or offset) for read() and write() operations. Would be good to expose that to us.

With regards to extending (inheritance) in Structures, you kind of do have it (in a funny kind of way) in C. SoundDescriptions are good examples. SoundDescriptionV1 includes SoundDescription:

struct SoundDescription { long decSize; //etc }

struct SoundDescriptionV1 { SoundDescription descPrimative; long somenewdata; }

Now in C, if we have a SoundDescriptionV1, we can cast that to a SoundDescription and get at the descPrimative innerds without dereferencing as the memory just follows on. In Java it would be nice if we could use inheritance:

public class SoundDescription extends Structure { public NativeLong descSize; //etc }

public class SoundDescriptionV1 extends SoundDescription { public NativeLong somenewdata; }

So we could simply do this:

SoundDescriptionV1 descV1 = new SoundDescriptionV1(); System.out.println(descV1.descSize);

Rather than having something like this:

System.out.println(descV1.descPrimative.descSize);

Now the latter case matches the C code better, but since we want JNA because we want to use Java, should we not be using an OO paradigm here? Especially as it shouldn't be too hard to do this.

Just some musings really. Hope it helps,

Paul.

On Jan 24, 2008 1:38 PM, Timothy Wall <twal@dev.java.net> wrote:

On Jan 24, 2008, at 8:30 AM, Paul Loy wrote:

Thanks Tim, I was using PointerByReference, but I now know the problem. As the SampleDescriptionHandle can be a variety of sizes it needs to be a "reallocatable block". Apple's docs for NewHandle specifically says:

"Do not try to manufacture your own handles without this function [NewHandle] by simply assigning the address of a variable of type Handle. The resulting 'fake handle' would not reference a relocatable block and would cause a system crash."

Now, while it doesn't always cause a system crash (in fact very rarely does it for me), it is not able to change this memory (due to it not being relocatable) and so I get garbage results. So I think I'm going to workaround, but just thought I'd let you know in case you can think of a way to handle (no pun intended) this in JNA.

So are they asking that instead of &ptr, they want you to pass the result of NewHandle?

If so, just call NewHandle (which presumably returns a Pointer, or you can define "Handle" which extends PointerType), and use the result as your argument. You can get the value with Pointer.getPointer(0) (which is the same as PointerByReference.getValue()).