Hey.
I'm doing my own numeric primitive. I could return numeric values, doing something like:
self pop: 1 thenPush: ( objectMemory integerObjectOf: 21 ).
What I couldn't do is find a way to return a string, for example 'Hello World'.
Thanks, David.
For more details.
With this code, I get a string and return it.
self var: #stringObj declareC: 'int stringObj'. self var: #stringPtr declareC: 'char *stringPtr'. self var: #stringSize declareC: 'int stringSize'. stringObj := objectMemory stackValue: 0. stringSize := objectMemory stSizeOf: stringObj. stringPtr := self cCoerce: (objectMemory arrayValueOf: stringObj) to: 'char *'.
But I can't replace stringObj := 'Hello World'. Why?
2012/6/30 David Leonhardt davidleonhardt@gmail.com
Hey.
I'm doing my own numeric primitive. I could return numeric values, doing something like:
self pop: 1 thenPush: ( objectMemory integerObjectOf:
21 ).
What I couldn't do is find a way to return a string, for example 'Hello World'.
Thanks, David.
On 30 June 2012 18:58, David Leonhardt davidleonhardt@gmail.com wrote:
For more details.
With this code, I get a string and return it.
self var: #stringObj declareC: 'int stringObj'. self var: #stringPtr declareC: 'char *stringPtr'. self var: #stringSize declareC: 'int stringSize'. stringObj := objectMemory stackValue: 0. stringSize := objectMemory stSizeOf: stringObj. stringPtr := self cCoerce: (objectMemory arrayValueOf: stringObj) to: 'char *'.
But I can't replace stringObj := 'Hello World'. Why?
Wait, you want to read from string object, or create a string object from C string?
For "returning" a string, first, you should instantiate an instance of ByteString, and then copy characters there.
// instantiating
stringOop := interpreterProxy instantiateClass: interpreterProxy classByteString indexableSize: size.
// getting a pointer to first character in bytestring instance <var: firstBytePtr type: 'char*'> firstBytePtr := interpreterProxy firstIndexableField: stringOop
// copying to/from 0 to: size-1 do:[ :i | firstBytePtr at: i put: (....) ]
2012/6/30 David Leonhardt davidleonhardt@gmail.com
Hey.
I'm doing my own numeric primitive. I could return numeric values, doing something like:
self pop: 1 thenPush: ( objectMemory integerObjectOf: 21 ).
What I couldn't do is find a way to return a string, for example 'Hello World'.
Thanks, David.
VM-beginners mailing list VM-beginners@lists.squeakfoundation.org http://lists.squeakfoundation.org/mailman/listinfo/vm-beginners
On Sat, Jun 30, 2012 at 12:15:01PM -0300, David Leonhardt wrote:
Hey.
I'm doing my own numeric primitive. I could return numeric values, doing something like:
self pop: 1 thenPush: ( objectMemory integerObjectOf: 21
).
What I couldn't do is find a way to return a string, for example 'Hello World'.
Here is one way to do it. This example is from OSProcessPlugin. If you load OSProcessPlugin from SqueakSource, you can find a few examples of how this is used in the primitives.
stringFromCString: aCString "Answer a new String copied from a null-terminated C string. Caution: This may invoke the garbage collector." | len newString p | <var: 'aCString' type: 'const char *'> <var: 'p' type: 'void *'> len := self cCode: 'strlen(aCString)' inSmalltalk: [aCString size]. newString := interpreterProxy instantiateClass: interpreterProxy classString indexableSize: len. p := interpreterProxy arrayValueOf: newString. self cCode: 'strncpy(p, aCString, len)' inSmalltalk: [ | s | s := interpreterProxy firstIndexableField: newString. (1 to: len) do: [:i | s at: i - 1 put: (aCString at: i) asciiValue]]. ^ newString
HTH, Dave
mmm.... it seems like I don't understand how to try with strings... ok, I need something more basic or more information. Someone know where can I read about how to try strings en SLang?
Are differences between how to try strings on numeric primitives and named primitives? Because I'm doing proves with numeric primitives.
Thank you very much.
On Sun, Jul 01, 2012 at 06:01:23PM -0300, David Leonhardt wrote:
mmm.... it seems like I don't understand how to try with strings... ok, I need something more basic or more information. Someone know where can I read about how to try strings en SLang?
When you create a new String object to return from your primitive, that object is part of the object memory managed by the VM. If you have the string "hello world" in some C code for your primitive, that string is not part of the object memory managed by the VM. It is just a null-terminated array of characters somewhere in the C program, allocated in memory somewhere outside of the Squeak object memory. This means that if you want your primitive to return a string, you should have your primitive create a new object of type String, copy the data from the C string into the data portion of the String object, and return that object as the result of the primitive.
Thus in order for a primitive to answer the string "hello world", the primitive should create a new instance of a String object with length 11. This object will (inside the object memory) have a header that indicates the type of object, and enough data space to hold 11 bytes of char data from a C string. If you copy "hello world" from the C string into the data area of the new String object, then you will have a 'hello world' String object in the Smalltalk object memory. You can put that object on the stack to return it as the result of a primitive call, and the result will be a primitive that answers the string 'hello world'.
Are differences between how to try strings on numeric primitives and named primitives? Because I'm doing proves with numeric primitives.
No, there is no difference between numeric primitives and named primitives. These are just two different ways of calling a primitive from the image. If you write a primitive to answer the string 'hello world', you will write it the same way regardless of whether it is a numbered primitive or a named primitive. But in general you should use named primitives whenever possible.
Dave
Ok, thank you!
David.
2012/7/2 David T. Lewis lewis@mail.msen.com
On Sun, Jul 01, 2012 at 06:01:23PM -0300, David Leonhardt wrote:
mmm.... it seems like I don't understand how to try with strings... ok, I need something more basic or more information. Someone know where can I read about how to try strings en SLang?
When you create a new String object to return from your primitive, that object is part of the object memory managed by the VM. If you have the string "hello world" in some C code for your primitive, that string is not part of the object memory managed by the VM. It is just a null-terminated array of characters somewhere in the C program, allocated in memory somewhere outside of the Squeak object memory. This means that if you want your primitive to return a string, you should have your primitive create a new object of type String, copy the data from the C string into the data portion of the String object, and return that object as the result of the primitive.
Thus in order for a primitive to answer the string "hello world", the primitive should create a new instance of a String object with length 11. This object will (inside the object memory) have a header that indicates the type of object, and enough data space to hold 11 bytes of char data from a C string. If you copy "hello world" from the C string into the data area of the new String object, then you will have a 'hello world' String object in the Smalltalk object memory. You can put that object on the stack to return it as the result of a primitive call, and the result will be a primitive that answers the string 'hello world'.
Are differences between how to try strings on numeric primitives and
named
primitives? Because I'm doing proves with numeric primitives.
No, there is no difference between numeric primitives and named primitives. These are just two different ways of calling a primitive from the image. If you write a primitive to answer the string 'hello world', you will write it the same way regardless of whether it is a numbered primitive or a named primitive. But in general you should use named primitives whenever possible.
Dave
On 02.07.2012, at 06:15, David T. Lewis wrote:
On Sun, Jul 01, 2012 at 06:01:23PM -0300, David Leonhardt wrote:
mmm.... it seems like I don't understand how to try with strings... ok, I need something more basic or more information. Someone know where can I read about how to try strings en SLang?
When you create a new String object to return from your primitive, that object is part of the object memory managed by the VM. If you have the string "hello world" in some C code for your primitive, that string is not part of the object memory managed by the VM. It is just a null-terminated array of characters somewhere in the C program, allocated in memory somewhere outside of the Squeak object memory. This means that if you want your primitive to return a string, you should have your primitive create a new object of type String, copy the data from the C string into the data portion of the String object, and return that object as the result of the primitive.
Thus in order for a primitive to answer the string "hello world", the primitive should create a new instance of a String object with length 11. This object will (inside the object memory) have a header that indicates the type of object, and enough data space to hold 11 bytes of char data from a C string. If you copy "hello world" from the C string into the data area of the new String object, then you will have a 'hello world' String object in the Smalltalk object memory. You can put that object on the stack to return it as the result of a primitive call, and the result will be a primitive that answers the string 'hello world'.
When copying from a C string to a Squeak string be sure to *not* copy the terminating zero byte.
"hello world" in C occupies 12 bytes - the 11 characters and an additional 0 to indicate the end of the string.
In Squeak, the character data would only consist of the 11 characters. The length is in the String object's header. If you were to accidentally copy the 0, this would be written in the memory after the String object, possibly corrupting the header of the next object in memory.
You must allocate the string object with the right size, because it cannot be changed later. E.g.
stringOOP := interpreterProxy instantiateClass: interpreterProxy classString indexableSize: 11.
stringOOP is an object reference - it does *not* point to the actual character data.
To get a pointer to the string's character data, use:
<var: 'stringPointer' type: 'char *'> stringPointer := interpreterProxy arrayValueOf: stringOOP.
That gives you a pointer where you can write your 11 characters to, by whatever means. Just be sure to not write more than 11 bytes.
When you're done, you can return the string from the primitive by pushing its OOP onto the stack. The Slang translator converts a Squeak return into a stack push (just look at the generated C code):
^ stringOOP
Are differences between how to try strings on numeric primitives and named primitives? Because I'm doing proves with numeric primitives.
No, there is no difference between numeric primitives and named primitives. These are just two different ways of calling a primitive from the image. If you write a primitive to answer the string 'hello world', you will write it the same way regardless of whether it is a numbered primitive or a named primitive. But in general you should use named primitives whenever possible.
Dave
- Bert -
Thank you all !!
This is de code I made. It seems to work:
primitiveHelloWorld | stringOop stringPtr size | <var: 'stringPtr' type: 'char*'> size := 11. stringOop := self instantiateClass: self classString indexableSize: size. stringPtr := self firstIndexableField: stringOop. 0 to: size-1 do:[ :i | stringPtr at: i put: ('Hello World' at: i) ]. self pop:1 thenPush: stringOop.
I had to use push, ^ not work at the same way.
Best regards, David.
On Tue, Jul 03, 2012 at 12:04:40AM -0300, David Leonhardt wrote:
Thank you all !!
This is de code I made. It seems to work:
primitiveHelloWorld | stringOop stringPtr size | <var: 'stringPtr' type: 'char*'> size := 11. stringOop := self instantiateClass: self classString indexableSize: size. stringPtr := self firstIndexableField: stringOop. 0 to: size-1 do:[ :i | stringPtr at: i put: ('Hello World' at: i) ]. self pop:1 thenPush: stringOop.
I had to use push, ^ not work at the same way.
Best regards, David.
Well done, I think you have solved the puzzle :)
Dave
On Mon, Jul 2, 2012 at 6:15 AM, David T. Lewis lewis@mail.msen.com wrote:
On Sun, Jul 01, 2012 at 06:01:23PM -0300, David Leonhardt wrote:
mmm.... it seems like I don't understand how to try with strings... ok, I need something more basic or more information. Someone know where can I read about how to try strings en SLang?
When you create a new String object to return from your primitive, that object is part of the object memory managed by the VM. If you have the string "hello world" in some C code for your primitive, that string is not part of the object memory managed by the VM. It is just a null-terminated array of characters somewhere in the C program, allocated in memory somewhere outside of the Squeak object memory. This means that if you want your primitive to return a string, you should have your primitive create a new object of type String, copy the data from the C string into the data portion of the String object, and return that object as the result of the primitive.
Thus in order for a primitive to answer the string "hello world", the primitive should create a new instance of a String object with length 11. This object will (inside the object memory) have a header that indicates the type of object, and enough data space to hold 11 bytes of char data from a C string. If you copy "hello world" from the C string into the data area of the new String object, then you will have a 'hello world' String object in the Smalltalk object memory. You can put that object on the stack to return it as the result of a primitive call, and the result will be a primitive that answers the string 'hello world'.
Excellent explanations.
Are differences between how to try strings on numeric primitives and
named
primitives? Because I'm doing proves with numeric primitives.
No, there is no difference between numeric primitives and named primitives. These are just two different ways of calling a primitive from the image. If you write a primitive to answer the string 'hello world', you will write it the same way regardless of whether it is a numbered primitive or a named primitive. But in general you should use named primitives whenever possible.
I wrote: http://marianopeck.wordpress.com/2011/06/03/primitives-pragmas-literals-and-... http://marianopeck.wordpress.com/2011/07/06/named-primitives/
maybe it helps with something.
Dave
VM-beginners mailing list VM-beginners@lists.squeakfoundation.org http://lists.squeakfoundation.org/mailman/listinfo/vm-beginners
2012/7/3 Mariano Martinez Peck marianopeck@gmail.com
Excellent explanations.
Yes, I had know what I was doing.
I wrote: http://marianopeck.wordpress.com/2011/06/03/primitives-pragmas-literals-and-... http://marianopeck.wordpress.com/2011/07/06/named-primitives/
maybe it helps with something.
Thanks!
-- Mariano http://marianopeck.wordpress.com
vm-beginners@lists.squeakfoundation.org