Trying to write a plugin - how to store a pointer

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Trying to write a plugin - how to store a pointer

tblanchard
For various reasons, I'm wanting to build a plugin to a library that  
requires me to hold onto pointers to things.  This means I need to  
store the pointer in an ivar in a squeak object and use it on  
subsequent calls.

Can I get away with using a SmallInteger for this?  Basically doing  
something like:

primNewContext
        | ctx |

        self export: true.
        self primitive: 'primCreateContext' parameters: #().
        self var: #ctx type: 'int'.
        ctx := self cCode: 'LIB_NewContext()'.
        ^ctx.

primDestroyContext: ctx
        self export: true.
        self primitive: 'primDestroyContext' parameters: #(SmallInteger).
        self cCode: 'LIB_DestroyContext((void*)ctx)'.

Or is this evil and I should consider a different technique?
If this is evil, what is the good way to store external addresses in  
ivars?

Thanks

Reply | Threaded
Open this post in threaded view
|

Re: Trying to write a plugin - how to store a pointer

johnmci
Although this seems correct at first, you run into trouble because  
SmallInteger has a finite range smaller than a 32bit integer.
Ignoring the 64bit needs  you would pass the value in as a Oops then  
do this

        pv := interpreterProxy positive32BitValueOf:  anAddressOops.
or perhaps
use positive64BitIntegerFor:  ?

on return you do this to pass the bits back.
        ^ interpreterProxy positive32BitIntegerFor:  address

It's likely you need to look at finalization and registering an  
external object (Smalltalk registerExternalObject: )
to ensure you free things when the smalltalk object is GCed, and to  
check to see if the object is still valid save after an image restart to
prevent passing in a bogus address which your C plugin would  
cheerfully attempt to use.  MPEGFile has some example code in it.


On 23-Jan-06, at 3:01 PM, Todd Blanchard wrote:

> For various reasons, I'm wanting to build a plugin to a library  
> that requires me to hold onto pointers to things.  This means I  
> need to store the pointer in an ivar in a squeak object and use it  
> on subsequent calls.
>
> Can I get away with using a SmallInteger for this?  Basically doing  
> something like:
>
> primNewContext
> | ctx |
>
> self export: true.
> self primitive: 'primCreateContext' parameters: #().
> self var: #ctx type: 'int'.
> ctx := self cCode: 'LIB_NewContext()'.
> ^ctx.
>
> primDestroyContext: ctx
> self export: true.
> self primitive: 'primDestroyContext' parameters: #(SmallInteger).
> self cCode: 'LIB_DestroyContext((void*)ctx)'.
>
> Or is this evil and I should consider a different technique?
> If this is evil, what is the good way to store external addresses  
> in ivars?
>
> Thanks

--
========================================================================
===
John M. McIntosh <[hidden email]> 1-800-477-2659
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
========================================================================
===


Reply | Threaded
Open this post in threaded view
|

Re: Trying to write a plugin - how to store a pointer

Andreas.Raab
In reply to this post by tblanchard
Generally, it's safer to use indexes (handles) that the VM maps to
appropriate pointers. That's because otherwise a restarted image might
invoke the primitive with a pointer from a previous session.

Cheers,
   - Andreas

Todd Blanchard wrote:

> For various reasons, I'm wanting to build a plugin to a library that  
> requires me to hold onto pointers to things.  This means I need to  
> store the pointer in an ivar in a squeak object and use it on  
> subsequent calls.
>
> Can I get away with using a SmallInteger for this?  Basically doing  
> something like:
>
> primNewContext
>     | ctx |
>
>     self export: true.
>     self primitive: 'primCreateContext' parameters: #().  
>     self var: #ctx type: 'int'.
>     ctx := self cCode: 'LIB_NewContext()'.
>     ^ctx.
>
> primDestroyContext: ctx
>     self export: true.
>     self primitive: 'primDestroyContext' parameters: #(SmallInteger).  
>     self cCode: 'LIB_DestroyContext((void*)ctx)'.
>
> Or is this evil and I should consider a different technique?
> If this is evil, what is the good way to store external addresses in  
> ivars?
>
> Thanks
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Trying to write a plugin - how to store a pointer

tblanchard
In reply to this post by johnmci
My plan is to add the class containing the pointer to the startup/
shutdown lists and make them zombies (I can't reasonably re-animate  
them with full state I don't think).

So I've got this:

primNewRuntime: bytesToAllocate

        | rtid size |

        self export: true.
        self var: #rtid type: 'void *'.
        self var: #size type: 'unsigned int'.
        size := interpreterProxy positive32BitValueOf:  bytesToAllocate.
        rtid := self cCode: 'LIB_NewRuntime(size)'.
        ^interpreterProxy positive32BitIntegerFor:  rtid.

Look OK?
Is there a good way to make it future proof for 64 bit addresses?  
Off the top of my head I can think of:

primNewRuntime: bytesToAllocate

        | rtid size |

        self export: true.
        self var: #rtid type: 'void *'.
        self var: #size type: 'unsigned int'.
        (self cCode: 'sizeof(void*)') = 4 ifTrue:
        [
                size := interpreterProxy positive32BitValueOf:  bytesToAllocate.
                rtid := self cCode: 'LIB_NewRuntime(size)'.
                ^interpreterProxy positive32BitIntegerFor:  rtid.
        ]
        ifFalse:
        [
                size := interpreterProxy positive64BitValueOf:  bytesToAllocate.
                rtid := self cCode: 'LIB_NewRuntime(size)'.
                ^interpreterProxy positive64BitIntegerFor:  rtid.
        ]

Maybe you know a better way?

On Jan 23, 2006, at 3:29 PM, John M McIntosh wrote:

> Although this seems correct at first, you run into trouble because  
> SmallInteger has a finite range smaller than a 32bit integer.
> Ignoring the 64bit needs  you would pass the value in as a Oops  
> then do this
>
> pv := interpreterProxy positive32BitValueOf:  anAddressOops.
> or perhaps
> use positive64BitIntegerFor:  ?
>
> on return you do this to pass the bits back.
> ^ interpreterProxy positive32BitIntegerFor:  address
>
> It's likely you need to look at finalization and registering an  
> external object (Smalltalk registerExternalObject: )
> to ensure you free things when the smalltalk object is GCed, and to  
> check to see if the object is still valid save after an image  
> restart to
> prevent passing in a bogus address which your C plugin would  
> cheerfully attempt to use.  MPEGFile has some example code in it.
>
>
> On 23-Jan-06, at 3:01 PM, Todd Blanchard wrote:
>
>> For various reasons, I'm wanting to build a plugin to a library  
>> that requires me to hold onto pointers to things.  This means I  
>> need to store the pointer in an ivar in a squeak object and use it  
>> on subsequent calls.
>>
>> Can I get away with using a SmallInteger for this?  Basically  
>> doing something like:
>>
>> primNewContext
>> | ctx |
>>
>> self export: true.
>> self primitive: 'primCreateContext' parameters: #().
>> self var: #ctx type: 'int'.
>> ctx := self cCode: 'LIB_NewContext()'.
>> ^ctx.
>>
>> primDestroyContext: ctx
>> self export: true.
>> self primitive: 'primDestroyContext' parameters: #(SmallInteger).
>> self cCode: 'LIB_DestroyContext((void*)ctx)'.
>>
>> Or is this evil and I should consider a different technique?
>> If this is evil, what is the good way to store external addresses  
>> in ivars?
>>
>> Thanks
>
> --
> ======================================================================
> =====
> John M. McIntosh <[hidden email]> 1-800-477-2659
> Corporate Smalltalk Consulting Ltd.  http://
> www.smalltalkconsulting.com
> ======================================================================
> =====
>


Reply | Threaded
Open this post in threaded view
|

Re: Trying to write a plugin - how to store a pointer

Andreas.Raab
 > Is there a good way to make it future proof for 64 bit addresses?

Generally, it's safer to use indexes (handles) that the VM maps to
appropriate pointers... wait ... I wrote that before, didn't I?

;-)


Todd Blanchard wrote:

> My plan is to add the class containing the pointer to the startup/
> shutdown lists and make them zombies (I can't reasonably re-animate  
> them with full state I don't think).
>
> So I've got this:
>
> primNewRuntime: bytesToAllocate
>
>     | rtid size |
>
>     self export: true.
>     self var: #rtid type: 'void *'.
>     self var: #size type: 'unsigned int'.
>     size := interpreterProxy positive32BitValueOf:  bytesToAllocate.
>     rtid := self cCode: 'LIB_NewRuntime(size)'.
>     ^interpreterProxy positive32BitIntegerFor:  rtid.
>
> Look OK?
> Is there a good way to make it future proof for 64 bit addresses?   Off
> the top of my head I can think of:
>
> primNewRuntime: bytesToAllocate
>
>     | rtid size |
>
>     self export: true.
>     self var: #rtid type: 'void *'.
>     self var: #size type: 'unsigned int'.
>     (self cCode: 'sizeof(void*)') = 4 ifTrue:
>     [
>         size := interpreterProxy positive32BitValueOf:  bytesToAllocate.
>         rtid := self cCode: 'LIB_NewRuntime(size)'.
>         ^interpreterProxy positive32BitIntegerFor:  rtid.
>     ]
>     ifFalse:
>     [
>         size := interpreterProxy positive64BitValueOf:  bytesToAllocate.
>         rtid := self cCode: 'LIB_NewRuntime(size)'.
>         ^interpreterProxy positive64BitIntegerFor:  rtid.
>     ]
>
> Maybe you know a better way?
>
> On Jan 23, 2006, at 3:29 PM, John M McIntosh wrote:
>
>> Although this seems correct at first, you run into trouble because  
>> SmallInteger has a finite range smaller than a 32bit integer.
>> Ignoring the 64bit needs  you would pass the value in as a Oops  then
>> do this
>>
>>     pv := interpreterProxy positive32BitValueOf:  anAddressOops.
>> or perhaps
>> use positive64BitIntegerFor:  ?
>>
>> on return you do this to pass the bits back.
>>     ^ interpreterProxy positive32BitIntegerFor:  address
>>
>> It's likely you need to look at finalization and registering an  
>> external object (Smalltalk registerExternalObject: )
>> to ensure you free things when the smalltalk object is GCed, and to  
>> check to see if the object is still valid save after an image  restart to
>> prevent passing in a bogus address which your C plugin would  
>> cheerfully attempt to use.  MPEGFile has some example code in it.
>>
>>
>> On 23-Jan-06, at 3:01 PM, Todd Blanchard wrote:
>>
>>> For various reasons, I'm wanting to build a plugin to a library  that
>>> requires me to hold onto pointers to things.  This means I  need to
>>> store the pointer in an ivar in a squeak object and use it  on
>>> subsequent calls.
>>>
>>> Can I get away with using a SmallInteger for this?  Basically  doing
>>> something like:
>>>
>>> primNewContext
>>>     | ctx |
>>>
>>>     self export: true.
>>>     self primitive: 'primCreateContext' parameters: #().  
>>>     self var: #ctx type: 'int'.
>>>     ctx := self cCode: 'LIB_NewContext()'.
>>>     ^ctx.
>>>
>>> primDestroyContext: ctx
>>>     self export: true.
>>>     self primitive: 'primDestroyContext' parameters: #(SmallInteger).  
>>>     self cCode: 'LIB_DestroyContext((void*)ctx)'.
>>>
>>> Or is this evil and I should consider a different technique?
>>> If this is evil, what is the good way to store external addresses  in
>>> ivars?
>>>
>>> Thanks
>>
>>
>> --
>> ======================================================================
>> =====
>> John M. McIntosh <[hidden email]> 1-800-477-2659
>> Corporate Smalltalk Consulting Ltd.  http:// www.smalltalkconsulting.com
>> ======================================================================
>> =====
>>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Trying to write a plugin - how to store a pointer

tblanchard
OK OK I get it now, I'm convinced. :-)

On Jan 23, 2006, at 11:00 PM, Andreas Raab wrote:

> > Is there a good way to make it future proof for 64 bit addresses?
>
> Generally, it's safer to use indexes (handles) that the VM maps to  
> appropriate pointers... wait ... I wrote that before, didn't I?
>
> ;-)
>
>
> Todd Blanchard wrote:
>> My plan is to add the class containing the pointer to the startup/  
>> shutdown lists and make them zombies (I can't reasonably re-
>> animate  them with full state I don't think).
>> So I've got this:
>> primNewRuntime: bytesToAllocate
>>     | rtid size |
>>     self export: true.
>>     self var: #rtid type: 'void *'.
>>     self var: #size type: 'unsigned int'.
>>     size := interpreterProxy positive32BitValueOf:  bytesToAllocate.
>>     rtid := self cCode: 'LIB_NewRuntime(size)'.
>>     ^interpreterProxy positive32BitIntegerFor:  rtid.
>> Look OK?
>> Is there a good way to make it future proof for 64 bit  
>> addresses?   Off the top of my head I can think of:
>> primNewRuntime: bytesToAllocate
>>     | rtid size |
>>     self export: true.
>>     self var: #rtid type: 'void *'.
>>     self var: #size type: 'unsigned int'.
>>     (self cCode: 'sizeof(void*)') = 4 ifTrue:
>>     [
>>         size := interpreterProxy positive32BitValueOf:  
>> bytesToAllocate.
>>         rtid := self cCode: 'LIB_NewRuntime(size)'.
>>         ^interpreterProxy positive32BitIntegerFor:  rtid.
>>     ]
>>     ifFalse:
>>     [
>>         size := interpreterProxy positive64BitValueOf:  
>> bytesToAllocate.
>>         rtid := self cCode: 'LIB_NewRuntime(size)'.
>>         ^interpreterProxy positive64BitIntegerFor:  rtid.
>>     ]
>> Maybe you know a better way?
>> On Jan 23, 2006, at 3:29 PM, John M McIntosh wrote:
>>> Although this seems correct at first, you run into trouble  
>>> because  SmallInteger has a finite range smaller than a 32bit  
>>> integer.
>>> Ignoring the 64bit needs  you would pass the value in as a Oops  
>>> then do this
>>>
>>>     pv := interpreterProxy positive32BitValueOf:  anAddressOops.
>>> or perhaps
>>> use positive64BitIntegerFor:  ?
>>>
>>> on return you do this to pass the bits back.
>>>     ^ interpreterProxy positive32BitIntegerFor:  address
>>>
>>> It's likely you need to look at finalization and registering an  
>>> external object (Smalltalk registerExternalObject: )
>>> to ensure you free things when the smalltalk object is GCed, and  
>>> to  check to see if the object is still valid save after an  
>>> image  restart to
>>> prevent passing in a bogus address which your C plugin would  
>>> cheerfully attempt to use.  MPEGFile has some example code in it.
>>>
>>>
>>> On 23-Jan-06, at 3:01 PM, Todd Blanchard wrote:
>>>
>>>> For various reasons, I'm wanting to build a plugin to a library  
>>>> that requires me to hold onto pointers to things.  This means I  
>>>> need to store the pointer in an ivar in a squeak object and use  
>>>> it  on subsequent calls.
>>>>
>>>> Can I get away with using a SmallInteger for this?  Basically  
>>>> doing something like:
>>>>
>>>> primNewContext
>>>>     | ctx |
>>>>
>>>>     self export: true.
>>>>     self primitive: 'primCreateContext' parameters: #().        
>>>> self var: #ctx type: 'int'.
>>>>     ctx := self cCode: 'LIB_NewContext()'.
>>>>     ^ctx.
>>>>
>>>> primDestroyContext: ctx
>>>>     self export: true.
>>>>     self primitive: 'primDestroyContext' parameters: #
>>>> (SmallInteger).       self cCode: 'LIB_DestroyContext((void*)ctx)'.
>>>>
>>>> Or is this evil and I should consider a different technique?
>>>> If this is evil, what is the good way to store external  
>>>> addresses  in ivars?
>>>>
>>>> Thanks
>>>
>>>
>>> --
>>> ====================================================================
>>> == =====
>>> John M. McIntosh <[hidden email]> 1-800-477-2659
>>> Corporate Smalltalk Consulting Ltd.  http://  
>>> www.smalltalkconsulting.com
>>> ====================================================================
>>> == =====
>>>


Reply | Threaded
Open this post in threaded view
|

Re: Trying to write a plugin - how to store a pointer

johnmci
In reply to this post by Andreas.Raab
Handles?
Sure you did, in that case you could use small integers and ignore  
the 32/64 bit issue. With a range check of course on the array you  
are indexing (32 or 64 bit addresses)
and a register as external object and cross check, or do a shutdown/
startup check to prevent passing in a bogus handle.

I'll also add you can say rtid := self LIB_NewRuntime: size   of  
course, the compiler will complain, but it will change that  into  
rtid = LIB_NewRuntime(size)


On 23-Jan-06, at 11:00 PM, Andreas Raab wrote:

> > Is there a good way to make it future proof for 64 bit addresses?
>
> Generally, it's safer to use indexes (handles) that the VM maps to  
> appropriate pointers... wait ... I wrote that before, didn't I?
>
> ;-)
>
>
> Todd Blanchard wrote:
>> My plan is to add the class containing the pointer to the startup/  
>> shutdown lists and make them zombies (I can't reasonably re-
>> animate  them with full state I don't think).
>> So I've got this:
>> primNewRuntime: bytesToAllocate
>>     | rtid size |
>>     self export: true.
>>     self var: #rtid type: 'void *'.
>>     self var: #size type: 'unsigned int'.
>>     size := interpreterProxy positive32BitValueOf:  bytesToAllocate.
>>     rtid := self cCode: 'LIB_NewRuntime(size)'.
>>     ^interpreterProxy positive32BitIntegerFor:  rtid.
>> Look OK?
>> Is there a good way to make it future proof for 64 bit  
>> addresses?   Off the top of my head I can think of:
>> primNewRuntime: bytesToAllocate
>>     | rtid size |
>>     self export: true.
>>     self var: #rtid type: 'void *'.
>>     self var: #size type: 'unsigned int'.
>>     (self cCode: 'sizeof(void*)') = 4 ifTrue:
>>     [
>>         size := interpreterProxy positive32BitValueOf:  
>> bytesToAllocate.
>>         rtid := self cCode: 'LIB_NewRuntime(size)'.
>>         ^interpreterProxy positive32BitIntegerFor:  rtid.
>>     ]
>>     ifFalse:
>>     [
>>         size := interpreterProxy positive64BitValueOf:  
>> bytesToAllocate.
>>         rtid := self cCode: 'LIB_NewRuntime(size)'.
>>         ^interpreterProxy positive64BitIntegerFor:  rtid.
>>     ]
>> Maybe you know a better way?
>> On Jan 23, 2006, at 3:29 PM, John M McIntosh wrote:
>>> Although this seems correct at first, you run into trouble  
>>> because  SmallInteger has a finite range smaller than a 32bit  
>>> integer.
>>> Ignoring the 64bit needs  you would pass the value in as a Oops  
>>> then do this
>>>
>>>     pv := interpreterProxy positive32BitValueOf:  anAddressOops.
>>> or perhaps
>>> use positive64BitIntegerFor:  ?
>>>
>>> on return you do this to pass the bits back.
>>>     ^ interpreterProxy positive32BitIntegerFor:  address
>>>
>>> It's likely you need to look at finalization and registering an  
>>> external object (Smalltalk registerExternalObject: )
>>> to ensure you free things when the smalltalk object is GCed, and  
>>> to  check to see if the object is still valid save after an  
>>> image  restart to
>>> prevent passing in a bogus address which your C plugin would  
>>> cheerfully attempt to use.  MPEGFile has some example code in it.
>>>
>>>
>>> On 23-Jan-06, at 3:01 PM, Todd Blanchard wrote:
>>>
>>>> For various reasons, I'm wanting to build a plugin to a library  
>>>> that requires me to hold onto pointers to things.  This means I  
>>>> need to store the pointer in an ivar in a squeak object and use  
>>>> it  on subsequent calls.
>>>>
>>>> Can I get away with using a SmallInteger for this?  Basically  
>>>> doing something like:
>>>>
>>>> primNewContext
>>>>     | ctx |
>>>>
>>>>     self export: true.
>>>>     self primitive: 'primCreateContext' parameters: #().        
>>>> self var: #ctx type: 'int'.
>>>>     ctx := self cCode: 'LIB_NewContext()'.
>>>>     ^ctx.
>>>>
>>>> primDestroyContext: ctx
>>>>     self export: true.
>>>>     self primitive: 'primDestroyContext' parameters: #
>>>> (SmallInteger).       self cCode: 'LIB_DestroyContext((void*)ctx)'.
>>>>
>>>> Or is this evil and I should consider a different technique?
>>>> If this is evil, what is the good way to store external  
>>>> addresses  in ivars?
>>>>
>>>> Thanks
>>>
>>>
>>> --
>>> ====================================================================
>>> == =====
>>> John M. McIntosh <[hidden email]> 1-800-477-2659
>>> Corporate Smalltalk Consulting Ltd.  http://  
>>> www.smalltalkconsulting.com
>>> ====================================================================
>>> == =====
>>>

--
========================================================================
===
John M. McIntosh <[hidden email]> 1-800-477-2659
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
========================================================================
===


Reply | Threaded
Open this post in threaded view
|

Re: Trying to write a plugin - how to store a pointer

Bert Freudenberg-3

Am 24.01.2006 um 08:06 schrieb John M McIntosh:
>
> I'll also add you can say rtid := self LIB_NewRuntime: size   of  
> course, the compiler will complain, but it will change that  into  
> rtid = LIB_NewRuntime(size)

After you hacked the compiler to allow underscores in identifiers, of  
course. I'm all for it for precisely this usage case, but there are  
backwards-compatibility issues.

- Bert -