And actually any object with non-pointer indexed instance variables can
be passed as #cObject. The catch is that it will break if the function causes a garbage collection, so this must be used with care! (The same shortcoming, actually, applies to garbage-collected CObjects). In the case of MD5 and TCP, however, it works great and removes a copy operation. In general, this is perfectly safe for functions that do not access the #cObject-passed values after creating new objects or having called back into smalltalk. In case the function does one of these two things, #cObject should be used only for heap-allocated data, or for pointers that were returned by another C function. Paolo libgst: 2008-05-15 Paolo Bonzini <[hidden email]> * libgst/cint.c: Allow passing any object with non-pointer indexed instance variables as a #cObject. packages/digest: 2008-05-15 Paolo Bonzini <[hidden email]> * md5.st: Pass data to C functions as #cObject. * sha1.st: Pass data to C functions as #cObject. packages/tcp: 2008-05-15 Paolo Bonzini <[hidden email]> * AbstractSocketImpl.st: Replace ByteArray buffers with garbage-collected CObjects. * IPSocketImpl.st: Likewise. * cfuncs.st: Change #byteArray and #byteArrayOut arguments to #cObject. diff --git a/doc/gst.texi b/doc/gst.texi index e091754..c9a0746 100644 --- a/doc/gst.texi +++ b/doc/gst.texi @@ -3320,7 +3320,16 @@ passed as @code{double} passed as @code{long double} @item cObject -C object value passed as @code{void *} +C object value passed as @code{void *}. + +Any class with non-pointer indexed instance variables can be passed as +a @code{#cObject}, and GNU Smalltalk will pass the address of the first indexed +instance variable. This however should never be done for functions that +allocate objects, call back into Smalltalk code or otherwise may cause +a garbage collection: after a GC, pointers passed as @code{#cObject} may be +invalidated. In this case, it is safer to pass every object as +@code{#smalltalk}, or to only pass @code{CObject}s that were returned +by a C function previously. @item cObjectPtr Pointer to C object value passed as @code{void **}. The @code{CObject} @@ -3354,6 +3363,7 @@ Table of parameter conversions: @item boolean @tab Boolean (True, False)@tab int @item byteArray @tab ByteArray @tab char * @item cObject @tab CObject @tab void * +@item cObject @tab ByteArray, etc. @tab void * @item cObjectPtr @tab CObject @tab void ** @item char @tab Boolean (True, False)@tab int @item char @tab Character @tab int (C promotion rule) diff --git a/libgst/cint.c b/libgst/cint.c index c4ed5d8..a1e91d6 100644 --- a/libgst/cint.c +++ b/libgst/cint.c @@ -1138,6 +1138,23 @@ push_smalltalk_obj (OOP oop, } } + /* #cObject can pass every object with non-pointer indexed instance + variables. */ + if (cType == CDATA_COBJECT) + { + switch (CLASS_INSTANCE_SPEC (class) & ISP_INDEXEDVARS) + { + case GST_ISP_FIXED: + case GST_ISP_POINTER: + break; + + default: + /* Byte indexed variables, pass the pointer through. */ + cp->u.ptrVal = OOP_TO_OBJ (oop)->data + CLASS_FIXED_FIELDS (class); + SET_TYPE (&ffi_type_pointer); + return; + } + } bad_type (class, cType); } diff --git a/packages/digest/md5.st b/packages/digest/md5.st index 58c33a0..1d1594e 100644 --- a/packages/digest/md5.st +++ b/packages/digest/md5.st @@ -49,13 +49,13 @@ MessageDigest subclass: MD5 [ combine: input size: len into: context [ <category: 'C call-outs'> - <cCall: 'MD5Update' returning: #void args: #(#byteArray #int #byteArrayOut)> + <cCall: 'MD5Update' returning: #void args: #(#cObject #int #cObject)> ] finalize: state in: digest [ <category: 'C call-outs'> - <cCall: 'MD5Final' returning: #void args: #(#byteArray #byteArrayOut)> + <cCall: 'MD5Final' returning: #void args: #(#cObject #cObject)> ] diff --git a/packages/digest/sha1.st b/packages/digest/sha1.st index feadac3..b76ad7d 100644 --- a/packages/digest/sha1.st +++ b/packages/digest/sha1.st @@ -49,13 +49,13 @@ MessageDigest subclass: SHA1 [ combine: input size: len into: context [ <category: 'C call-outs'> - <cCall: 'SHA1Update' returning: #void args: #(#byteArray #int #byteArrayOut)> + <cCall: 'SHA1Update' returning: #void args: #(#cObject #int #cObject)> ] finalize: state in: digest [ <category: 'C call-outs'> - <cCall: 'SHA1Final' returning: #void args: #(#byteArray #byteArrayOut)> + <cCall: 'SHA1Final' returning: #void args: #(#cObject #cObject)> ] diff --git a/packages/tcp/AbstractSocketImpl.st b/packages/tcp/AbstractSocketImpl.st index 79d6f74..32d03d0 100644 --- a/packages/tcp/AbstractSocketImpl.st +++ b/packages/tcp/AbstractSocketImpl.st @@ -78,15 +78,14 @@ FileDescriptor subclass: AbstractSocketImpl [ active server socket." <category: 'socket operations'> - | peer sizePtr newFD fd | + | peer addrLen newFD fd | peer := ByteArray new: CSockAddrStruct sizeof. - sizePtr := ByteArray new: CInt sizeof. - sizePtr intAt: 1 put: CSockAddrStruct sizeof. + addrLen := CInt gcValue: CSockAddrStruct sizeof. (fd := self fd) isNil ifTrue: [ ^SystemExceptions.EndOfStream signal ]. newFD := self accept: fd peer: peer - addrLen: sizePtr. + addrLen: addrLen. ^(implementationClass on: newFD) hasBeenBound; hasBeenConnectedTo: peer; @@ -192,15 +191,14 @@ FileDescriptor subclass: AbstractSocketImpl [ local endpoint of the socket." <category: 'socket operations'> - | sock sizePtr fd | + | sock addrLen fd | sock := ByteArray new: CSockAddrStruct sizeof. - sizePtr := ByteArray new: CInt sizeof. - sizePtr intAt: 1 put: CSockAddrStruct sizeof. + addrLen := CInt gcValue: CSockAddrStruct sizeof. (fd := self fd) isNil ifTrue: [ ^nil ]. self getSockName: fd addr: sock - addrLen: sizePtr. + addrLen: addrLen. ^sock ] @@ -273,17 +271,16 @@ FileDescriptor subclass: AbstractSocketImpl [ so this will be rarely used." <category: 'socket options'> - | result sizeArray fd | + | result len fd | result := ByteArray new: size. - sizeArray := ByteArray new: CInt sizeof. - sizeArray intAt: 1 put: size. + len := CInt gcValue: size. (fd := self fd) isNil ifTrue: [ ^nil ]. self option: fd level: level at: opt get: result - size: sizeArray. + size: len. ^result ] @@ -538,15 +535,14 @@ AbstractSocketImpl subclass: SocketImpl [ remote endpoint of the socket." <category: 'socket operations'> - | peer sizePtr fd | + | peer addrLen fd | peer := ByteArray new: CSockAddrStruct sizeof. - sizePtr := ByteArray new: CInt sizeof. - sizePtr intAt: 1 put: CSockAddrStruct sizeof. + addrLen := CInt gcValue: CSockAddrStruct sizeof. (fd := self fd) isNil ifTrue: [ ^nil ]. self getPeerName: self fd addr: peer - addrLen: sizePtr. + addrLen: addrLen. ^peer ] @@ -638,10 +634,9 @@ AbstractSocketImpl subclass: DatagramSocketImpl [ <category: 'socket operations'> | address port data from addrLen fd | - addrLen := ByteArray new: CInt sizeof. data := ByteArray new: self bufferSize. from := ByteArray new: CSockAddrStruct sizeof. - addrLen intAt: 1 put: from size. + addrLen := CInt gcValue: from size. (fd := self fd) isNil ifTrue: [ ^SystemExceptions.EndOfStream signal ]. self receive: fd @@ -664,7 +659,7 @@ AbstractSocketImpl subclass: DatagramSocketImpl [ <category: 'socket operations'> | size receiver fd | theReceiver isNil - ifTrue: [receiver := size := 0] + ifTrue: [receiver := nil. size := 0] ifFalse: [receiver := theReceiver port: port. size := receiver size]. diff --git a/packages/tcp/IPSocketImpl.st b/packages/tcp/IPSocketImpl.st index bffa5b2..65f0d45 100644 --- a/packages/tcp/IPSocketImpl.st +++ b/packages/tcp/IPSocketImpl.st @@ -340,22 +340,20 @@ SocketAddress subclass: IPAddress [ <category: 'private'> port < 0 | (port > 65535) ifTrue: [self error: 'port out of range']. ^(ByteArray new: CSockAddrStruct sizeof) + "Write sin_addr" replaceFrom: CSockAddrStruct sizeof - 11 to: CSockAddrStruct sizeof - 8 with: address startingAt: 1; + + "Write sin_family = AF_INET in host order" shortAt: 1 put: self class addressFamily; + + "Write sin_port in network order (big endian)" at: CSockAddrStruct sizeof - 13 put: port // 256; at: CSockAddrStruct sizeof - 12 put: (port bitAnd: 255); yourself - "Write sin_addr" - - "Write sin_family = AF_INET in host order" - - "Write sin_port in network order (big endian)" - - "ouf..." ] ] @@ -548,6 +546,10 @@ RawSocketImpl subclass: ICMPSocketImpl [ Eval [ CStruct newStruct: #CSockAddrStruct - declaration: #(#(#sinFamily #short) #(#sinPort #(#array #byte 2)) #(#sinAddr #(#array #byte 4)) #(#sinZero #(#array #byte 8))) + declaration: #( + #(#sinFamily #short) + #(#sinPort #(#array #byte 2)) + #(#sinAddr #(#array #byte 4)) + #(#sinZero #(#array #byte 8))) ] diff --git a/packages/tcp/cfuncs.st b/packages/tcp/cfuncs.st index f0d4010..0cf2c1f 100644 --- a/packages/tcp/cfuncs.st +++ b/packages/tcp/cfuncs.st @@ -184,7 +184,7 @@ SocketAddress class extend [ primName: address len: len type: addressFamily [ <category: 'C call-outs'> <cCall: 'TCPgetHostByAddr' returning: #stringOut - args: #(#byteArray #int #int)> + args: #(#cObject #int #int)> ] @@ -204,7 +204,7 @@ IPAddress class extend [ primAnyLocalAddress: hostName in: byteArray [ <category: 'C call-outs'> <cCall: 'TCPgetAnyLocalAddress' returning: #void - args: #(#string #byteArrayOut)> + args: #(#string #cObject)> ] @@ -217,21 +217,21 @@ AbstractSocketImpl extend [ accept: socket peer: peer addrLen: len [ <category: 'C call-outs'> <cCall: 'TCPaccept' returning: #int - args: #(#int #byteArrayOut #byteArray )> + args: #(#int #cObject #cObject )> ] bind: socket to: addr addrLen: len [ <category: 'C call-outs'> <cCall: 'TCPbind' returning: #int - args: #(#int #byteArray #int )> + args: #(#int #cObject #int )> ] connect: socket to: addr addrLen: len [ <category: 'C call-outs'> <cCall: 'TCPconnect' returning: #int - args: #(#int #byteArray #int )> + args: #(#int #cObject #int )> ] @@ -245,42 +245,42 @@ AbstractSocketImpl extend [ getPeerName: socket addr: addr addrLen: len [ <category: 'C call-outs'> <cCall: 'TCPgetpeername' returning: #int - args: #(#int #byteArrayOut #byteArray )> + args: #(#int #cObject #cObject )> ] getSockName: socket addr: addr addrLen: len [ <category: 'C call-outs'> <cCall: 'TCPgetsockname' returning: #int - args: #(#int #byteArrayOut #byteArray )> + args: #(#int #cObject #cObject )> ] receive: socket buffer: buf size: len flags: flags from: addr size: addrLen [ <category: 'C call-outs'> <cCall: 'TCPrecvfrom' returning: #int - args: #(#int #byteArrayOut #int #int #byteArray #byteArrayOut )> + args: #(#int #cObject #int #int #cObject #cObject )> ] send: socket buffer: buf size: len flags: flags to: addr size: addrLen [ <category: 'C call-outs'> <cCall: 'TCPsendto' returning: #int - args: #(#int #byteArray #int #int #unknown #int )> + args: #(#int #cObject #int #int #cObject #int )> ] option: socket level: level at: name put: value size: len [ <category: 'C call-outs'> <cCall: 'TCPsetsockopt' returning: #int - args: #(#int #int #int #byteArray #int )> + args: #(#int #int #int #cObject #int )> ] option: socket level: level at: name get: value size: len [ <category: 'C call-outs'> <cCall: 'TCPgetsockopt' returning: #int - args: #(#int #int #int #byteArrayOut #byteArrayOut )> + args: #(#int #int #int #cObject #cObject )> ] @@ -300,21 +300,21 @@ AbstractSocketImpl class extend [ accept: socket peer: peer addrLen: len [ <category: 'C call-outs'> <cCall: 'TCPaccept' returning: #int - args: #(#int #byteArrayOut #byteArray )> + args: #(#int #cObject #cObject )> ] bind: socket to: addr addrLen: len [ <category: 'C call-outs'> <cCall: 'TCPbind' returning: #int - args: #(#int #byteArray #int )> + args: #(#int #cObject #int )> ] connect: socket to: addr addrLen: len [ <category: 'C call-outs'> <cCall: 'TCPconnect' returning: #int - args: #(#int #byteArray #int )> + args: #(#int #cObject #int )> ] @@ -328,42 +328,42 @@ AbstractSocketImpl class extend [ getPeerName: socket addr: addr addrLen: len [ <category: 'C call-outs'> <cCall: 'TCPgetpeername' returning: #int - args: #(#int #byteArrayOut #byteArray )> + args: #(#int #cObject #cObject )> ] getSockName: socket addr: addr addrLen: len [ <category: 'C call-outs'> <cCall: 'TCPgetsockname' returning: #int - args: #(#int #byteArrayOut #byteArray )> + args: #(#int #cObject #cObject )> ] receive: socket buffer: buf size: len flags: flags from: addr size: addrLen [ <category: 'C call-outs'> <cCall: 'TCPrecvfrom' returning: #int - args: #(#int #byteArrayOut #int #int #byteArray #byteArrayOut )> + args: #(#int #cObject #int #int #cObject #cObject )> ] send: socket buffer: buf size: len flags: flags to: addr size: addrLen [ <category: 'C call-outs'> <cCall: 'TCPsendto' returning: #int - args: #(#int #byteArray #int #int #unknown #int )> + args: #(#int #cObject #int #int #cObject #int )> ] option: socket level: level at: name put: value size: len [ <category: 'C call-outs'> <cCall: 'TCPsetsockopt' returning: #int - args: #(#int #int #int #byteArray #int )> + args: #(#int #int #int #cObject #int )> ] option: socket level: level at: name get: value size: len [ <category: 'C call-outs'> <cCall: 'TCPgetsockopt' returning: #int - args: #(#int #int #int #byteArrayOut #byteArrayOut )> + args: #(#int #int #int #cObject #cObject )> ] _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
Free forum by Nabble | Edit this page |