author | Stefan Vogel <sv@exept.de> |
Mon, 20 Dec 2010 14:34:54 +0100 | |
changeset 13175 | ea7102cce519 |
parent 13105 | 8c9757dcd4ea |
child 13180 | 206304310ce0 |
permissions | -rw-r--r-- |
" COPYRIGHT (c) 1995 by Claus Gittinger All Rights Reserved This software is furnished under a license and may be used only in accordance with the terms of that license and with the inclusion of the above copyright notice. This software may not be provided or otherwise made available to, or used by, any other person. No title to or ownership of the software is hereby transferred. " "{ Package: 'stx:libbasic' }" Object subclass:#ExternalAddress instanceVariableNames:'address*' classVariableNames:'' poolDictionaries:'' category:'System-Support' ! !ExternalAddress class methodsFor:'documentation'! copyright " COPYRIGHT (c) 1995 by Claus Gittinger All Rights Reserved This software is furnished under a license and may be used only in accordance with the terms of that license and with the inclusion of the above copyright notice. This software may not be provided or otherwise made available to, or used by, any other person. No title to or ownership of the software is hereby transferred. " ! documentation " Instances of this class represent external (non-Smalltalk) addresses. They are only useful to represent handles as returned by C functions as smalltalk objects. For example, Window- or WidgetIDs (which are actually 32 bit pointers) could be represented this way (better create a handle-subclass for it, to care for proper finalization). (you should not use SmallIntegers for this, since they can only represent 31 bits; LargeIntegers could be used in theory, but it is not a very good style to do so, since it makes things a bit cryptic - having ExternalAddresses around makes things pretty clear in inspectors etc.). There is not much you can do with ExternalAddresses on the smalltalk level; creation/use should be done in primitive C-code via __MKEXTERNALADDRESS(voidPtr) and __ExternalAddressVal(obj). ExternallAddresses are much like ExternalBytes - however, the latter allow you to access bytes via indexed at:/at:put: messages. ExternalAddresses do not allow such accesses (they are meant to remain anonymous, opaque handles). Also, memory blocks which are freeable should be represented as ExternalBytes. [author:] Claus Gittinger [see also:] ByteArray ExternalBytes ExternalFunction ( how to write primitive code :html: programming/primitive.html ) " ! examples " To pass some C-pointer from primitive code to smalltalk: ... RETURN (__MKEXTERNALADDRESS(foo)); pass it back to C and use it there: ... if (__isExternalAddress(anExternalAddress)) { ptr = __externalAddressVal(anExternalAddress)); } ... concrete example: test1 %{ static char foo[] = {'h', 'e' ,'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '\n'}; RETURN (__MKEXTERNALADDRESS(foo)); %} test2:anExternalAddress %{ if (__isExternalAddress(anExternalAddress)) { printf(__externalAddressVal(anExternalAddress)); RETURN (self); } %} " ! ! !ExternalAddress class methodsFor:'instance creation'! newAddress:addr ^ self new setAddress:addr ! ! !ExternalAddress class methodsFor:'queries'! isBuiltInClass "return true if this class is known by the run-time-system. Here, true is returned." ^ self == ExternalAddress "Modified: / 11.6.1998 / 17:12:40 / cg" ! pointerSize "answer the size in bytes of a pointer" %{ /* NOCONTEXT */ RETURN(__mkSmallInteger(sizeof(void *))); %}. " self pointerSize " ! ! !ExternalAddress methodsFor:'Compatibility-Squeak'! beNull self setAddress:0 ! isNull ^ self address = 0 "Created: / 26-10-2010 / 23:17:57 / cg" ! ! !ExternalAddress methodsFor:'accessing'! address "return the start address as an integer" %{ /* NOCONTEXT */ unsigned INT addr; addr = (unsigned INT)__INST(address_); RETURN ( __MKUINT(addr)); %} ! instVarAt:index "redefined to suppress direct access to my address, which is a non-object" index == 1 ifTrue:[^ self address]. ^ super instVarAt:index "Created: / 3.9.1999 / 13:47:03 / ps" ! instVarAt:index put:newAddress "redefined to suppress direct access to my address, which is a non-object" index == 1 ifTrue:[ self setAddress:newAddress. ^ newAddress ]. ^ super instVarAt:index put:newAddress "Created: / 3.9.1999 / 14:31:57 / ps" ! ! !ExternalAddress methodsFor:'comparing'! = anExternalAddress "return true, if two externalAddress instance represent the same C pointer" %{ /* NOCONTEXT */ if (__isExternalAddress(anExternalAddress) && (__externalAddressVal(self) == __externalAddressVal(anExternalAddress))) { RETURN (true); } %}. ^ false ! hash "return a number useful for hashing" %{ /* NOCONTEXT */ unsigned INT addr = (unsigned INT) __externalAddressVal(self); if (addr > _MAX_INT) { if ((addr & 1) == 0) { addr >>= 1; } if (addr > _MAX_INT) { if ((addr & 1) == 0) { addr >>= 1; } } if (addr > _MAX_INT) { addr &= _MAX_INT; } } else { addr <<= 1; if (addr <= _MAX_INT) { addr <<= 1; if (addr <= _MAX_INT) { addr <<= 1; } } addr >>= 1; } RETURN (__mkSmallInteger(addr)); %} ! ! !ExternalAddress methodsFor:'converting'! asExternalAddress "convert to an ExternalAddress. Useful to convert subclasses" %{ /* NOCONTEXT */ if (__qClass(self) == @global(ExternalAddress)) { RETURN(self) } RETURN(__MKEXTERNALADDRESS(__INST(address_))); %}. " (ExternalAddress newAddress:16r12345678) asExternalAddress " ! asExternalBytes "return an ExternalBytes object pointing to where the receiver points to. Use of this is not recommended; primitives which return externalAddresses dont think that access to the memory is required/useful, while primitives which do think so should return an externalBytes instance right away." %{ /* NOCONTEXT */ RETURN(__MKEXTERNALBYTES(__INST(address_))); %} " (ExternalAddress newAddress:16r12345678) asExternalBytes " ! copyCStringFromHeap ^ self asExternalBytes copyCStringFromHeap ! ! !ExternalAddress methodsFor:'printing & storing'! printOn:aStream "return a printed representation of the receiver" self class name printOn:aStream. aStream nextPutAll:' at:'. self address printOn:aStream base:16. ! ! !ExternalAddress methodsFor:'private-accessing'! setAddress:anInteger "set the address" %{ /* NOCONTEXT */ unsigned INT addr; if (__isSmallInteger(anInteger)) { addr = __intVal(anInteger); } else { addr = __unsignedLongIntVal(anInteger); } __INST(address_) = (OBJ)addr; %} ! setAddressFromBytes:aByteArray "set the address from a pointer to which we have a pointer to" %{ /* NOCONTEXT */ if (__isByteArrayLike(aByteArray)) { if (__byteArraySize(aByteArray) == sizeof(void *)) { __INST(address_) = (OBJ)(((void **)__byteArrayVal(aByteArray))[0]); RETURN (self); } } %}. self primitiveFailed. "Created: / 27-07-2006 / 14:37:57 / fm" "Modified: / 07-08-2006 / 15:16:32 / fm" ! ! !ExternalAddress class methodsFor:'documentation'! version ^ '$Header: /cvs/stx/stx/libbasic/ExternalAddress.st,v 1.26 2010-10-26 21:45:34 cg Exp $' ! version_CVS ^ '$Header: /cvs/stx/stx/libbasic/ExternalAddress.st,v 1.26 2010-10-26 21:45:34 cg Exp $' ! !