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
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 johnmci@smalltalkconsulting.com 1-800-477-2659 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com ======================================================================== ===
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 johnmci@smalltalkconsulting.com 1-800-477-2659 Corporate Smalltalk Consulting Ltd. http:// www.smalltalkconsulting.com ====================================================================== =====
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 johnmci@smalltalkconsulting.com 1-800-477-2659 Corporate Smalltalk Consulting Ltd. http:// www.smalltalkconsulting.com ====================================================================== =====
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 johnmci@smalltalkconsulting.com 1-800-477-2659 Corporate Smalltalk Consulting Ltd. http:// www.smalltalkconsulting.com ==================================================================== == =====
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 johnmci@smalltalkconsulting.com 1-800-477-2659 Corporate Smalltalk Consulting Ltd. http:// www.smalltalkconsulting.com ==================================================================== == =====
-- ======================================================================== === John M. McIntosh johnmci@smalltalkconsulting.com 1-800-477-2659 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com ======================================================================== ===
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 -
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
vm-dev@lists.squeakfoundation.org