[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Help-smalltalk] [PATCH] Pass ByteArray as #cObject
From: |
Paolo Bonzini |
Subject: |
[Help-smalltalk] [PATCH] Pass ByteArray as #cObject |
Date: |
Thu, 15 May 2008 08:22:57 +0200 |
User-agent: |
Thunderbird 2.0.0.14 (Macintosh/20080421) |
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 <address@hidden>
* libgst/cint.c: Allow passing any object with non-pointer indexed
instance variables as a #cObject.
packages/digest:
2008-05-15 Paolo Bonzini <address@hidden>
* 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 <address@hidden>
* 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
address@hidden, 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 *
address@hidden 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 )>
]
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Help-smalltalk] [PATCH] Pass ByteArray as #cObject,
Paolo Bonzini <=