Slang - self primitive: parameters:

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Slang - self primitive: parameters:

Brad Fuller
Hello all,

I'm trying to generate a 'ulong' in Slang using the "self primitive:
parameters:" method.

    self primitive: 'primitivePutOutputParms'
        parameters: #(#SmallInteger #SmallInteger #Unsigned #Float #String).

But, I don't know how.  #Float generates a double and SmallInteger
generates "int".  What are the other ones? Is this a dictionary?
When I use #Unsigned it generates:

    int parm2;

   
interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(2),
"Unsigned"));
    parm2 = interpreterProxy->stackValue(2);

which I don't think I want, do I?

Also, does anyone know how to generate void pointer?: (void *)?

brad


Reply | Threaded
Open this post in threaded view
|

Re: Slang - self primitive: parameters:

Brad Fuller
Brad Fuller wrote:

> Hello all,
>
> I'm trying to generate a 'ulong' in Slang using the "self primitive:
> parameters:" method.
>
>    self primitive: 'primitivePutOutputParms'
>        parameters: #(#SmallInteger #SmallInteger #Unsigned #Float
> #String).
>
> But, I don't know how.  #Float generates a double and SmallInteger
> generates "int".  What are the other ones? Is this a dictionary?
> When I use #Unsigned it generates:
>
>    int parm2;
>
>    
> interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(2),
> "Unsigned"));
>    parm2 = interpreterProxy->stackValue(2);
>
> which I don't think I want, do I?
>
> Also, does anyone know how to generate void pointer?: (void *)?

Further to add to this thread:

I need to return a char pointer from a primitive back to Squeak, but I
can't find out how to do it in Slang. Can anyone give me pointers?


Using:
self returnTypeC: 'char *'
works great for the return of a routine, but I need the return value to
be pushed on the stack for return back to Squeak.

what I have is this which doesn't work quite right.. (primarily because
I can't quite get the whole idea of this):

primitiveGetText
    | text |

    self var: #text declareC: 'char *text'.
    self primitive: 'primitiveGetText'.
    text := self cCode: 'GetText()'.
    ^text asValue: String.

Which results in:

EXPORT(int) primitiveGetText(void) {
    char *text;
    int _return_value;

    text = GetText();
    _return_value = ((char *) interpreterProxy->firstIndexableField(text));
    if (interpreterProxy->failed()) {
        return null;
    }
    interpreterProxy->popthenPush(1, _return_value);
    return null;
}

I've been fooling with this all day.. getting frustrating!

thanks,
brad

Reply | Threaded
Open this post in threaded view
|

Re: Slang - self primitive: parameters:

Andreas.Raab
Brad Fuller wrote:
> I've been fooling with this all day.. getting frustrating!

If you get frustrated enough and decide to (instead of tricking
SmartSyntaxPlugin into doing the right thing) do the hard way, here is how:

primitiveGetText
    | text sz oop ptr |
    self export: true.
    self var: #text type: 'char*'.
    self var: #ptr type: 'char*'.
    text := self cCode: 'GetText()'.
    sz := self strlen: sz.
    "Create new String object of appropriate size"
    oop := interpreterProxy
              instantiateClass: interpreterProxy classString
              indexableSize: sz.
    "Copy data"
    ptr := interpreterProxy firstIndexableField: oop.
    self cCode:'memcpy(ptr, text, sz)'.
    "Return oop"
    interpreterProxy pop: interpreterProxy methodArgumentCount+1.
    interpreterProxy push: oop.


Cheers,
   - Andreas

Reply | Threaded
Open this post in threaded view
|

Re: Slang - self primitive: parameters:

timrowledge
In reply to this post by Brad Fuller

On 13-Dec-05, at 6:03 PM, Brad Fuller wrote:

> Brad Fuller wrote:
>
>> Hello all,
>>
>> I'm trying to generate a 'ulong' in Slang using the "self  
>> primitive: parameters:" method.
Don't think that is likely to work. There isn't really an unsigned  
long type in Smalltalk - the class Unsigned is only used in some of  
the strange TestOSAPlugin prims along with #asOop: which tries to  
make a valid positive 32bit  number out of it. Take a look for  
references to the class Unsigned to see what I mean.

If what you want is to extract the param and treat it as an unsigned  
long (you might also need to think about 64bitness) then you will  
need to pass in a SmallInteger or possibly a LargePositiveInteger -  
which means using Oop - and coerce it later.

>>
>>    self primitive: 'primitivePutOutputParms'
>>        parameters: #(#SmallInteger #SmallInteger #Unsigned #Float  
>> #String).
>>
>> But, I don't know how.  #Float generates a double and SmallInteger  
>> generates "int".  What are the other ones? Is this a dictionary?
>> When I use #Unsigned it generates:
>>
>>    int parm2;
>>
>>    interpreterProxy->success(interpreterProxy->isKindOf
>> (interpreterProxy->stackValue(2), "Unsigned"));
>>    parm2 = interpreterProxy->stackValue(2);
>>
>> which I don't think I want, do I?
Nope. It probably ought to raise an error rather than just sticking  
something meaningless in there.

>>
>> Also, does anyone know how to generate void pointer?: (void *)?
coerce it - as in "self cCoerce: fred to: 'void *' "

>
> Further to add to this thread:
>
> I need to return a char pointer from a primitive back to Squeak,  
> but I can't find out how to do it in Slang. Can anyone give me  
> pointers?
I doubt you really want to return a char pointer; what use would it be?
If you really want to have the pointer - it is a real not-in-object-
space pointer isn't it? - then you'd need to return it as a number  
and then do the right thing with it when you call some other prim  
that can make sense of it. For example, we pass file structure  
pointers up to Squeak from the FilePlugin and only look at them in  
prims.
If you actually want the String, then you need to create a String  
object and copy the chars from your pointer into the String instance.
Take a look at MIDIPlugin>primitiveMIDIGetPortName: where the nameObj  
is a createdString and the C call memcpy() is used to fill it.

>
>
> Using:
> self returnTypeC: 'char *'
> works great for the return of a routine, but I need the return  
> value to be pushed on the stack for return back to Squeak.
As mentioned above, you probably don't want the actual char * from  
what I can see.

>
> what I have is this which doesn't work quite right.. (primarily  
> because I can't quite get the whole idea of this):
>
> primitiveGetText
>    | text |
>
>    self var: #text declareC: 'char *text'.
ok
>    self primitive: 'primitiveGetText'.
ok - note you are at liberty to name the prim anything here, "self  
primitve: 'primFred' " would work as well. You have to remember to  
actually *call* primFred of course.
>    text := self cCode: 'GetText()'.
ok - note that you can get away with replacing "self cCode:'strlen
(fred)' " with "self strlen: fred" and it has the virtue that you can  
implement #strlen: somewhere for simulation purposes.
>    ^text asValue: String.
bad; this is not converting text into a String, it is assuming text  
is already a String object and giving you the C pointer that would be  
valid if you treat it as a string. Poor choice of name, maybe. More  
often than not you'll see the code rather more directly using  
"interpreterProxy firstIndexableField: nameOop" instead.


tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim



Reply | Threaded
Open this post in threaded view
|

Re: Slang - self primitive: parameters:

Brad Fuller
tim Rowledge wrote:

>
> On 13-Dec-05, at 6:03 PM, Brad Fuller wrote:
>
>> Brad Fuller wrote:
>>
>>> Hello all,
>>>
>>> I'm trying to generate a 'ulong' in Slang using the "self  
>>> primitive: parameters:" method.
>>
> Don't think that is likely to work. There isn't really an unsigned  
> long type in Smalltalk - the class Unsigned is only used in some of  
> the strange TestOSAPlugin prims along with #asOop: which tries to  
> make a valid positive 32bit  number out of it. Take a look for  
> references to the class Unsigned to see what I mean.
>
> If what you want is to extract the param and treat it as an unsigned  
> long (you might also need to think about 64bitness) then you will  
> need to pass in a SmallInteger or possibly a LargePositiveInteger -  
> which means using Oop - and coerce it later.

I wanted to make sure that I chose the right "type" to work on all
platforms today. I didn't even think about 64bit! Thanks.
 
The result in this particular param is a bit representation in 16bits
and one of the potential returns is 0x80000000. So, if I use
LargePositiveInteger would that be ok and not have a possible conversion
issue (going from C to Squeak) with the high bit set? I'm still trying
to get my head around all of this. I'm going thru Andrew's "Extending
the Squeak Virtual Machine", which is great, but not all the easy tricks
(like self primitive: parameters:) are in there --- so I'm combing the
other plugins for help.

> Further to add to this thread:
>
> I need to return a char pointer from a primitive back to Squeak,  but
> I can't find out how to do it in Slang. Can anyone give me  pointers?
> I doubt you really want to return a char pointer; what use would it be?
> If you really want to have the pointer - it is a real not-in-object-
> space pointer isn't it? - then you'd need to return it as a number  
> and then do the right thing with it when you call some other prim  
> that can make sense of it. For example, we pass file structure  
> pointers up to Squeak from the FilePlugin and only look at them in  
> prims.
> If you actually want the String, then you need to create a String  
> object and copy the chars from your pointer into the String instance.

Yes, I do really want the text that the char * is pointing to. Duh.

> Take a look at MIDIPlugin>primitiveMIDIGetPortName: where the nameObj  
> is a createdString and the C call memcpy() is used to fill it.

>>    ^text asValue: String.
>
> bad; this is not converting text into a String, it is assuming text  
> is already a String object and giving you the C pointer that would be  
> valid if you treat it as a string. Poor choice of name, maybe. More  
> often than not you'll see the code rather more directly using  
> "interpreterProxy firstIndexableField: nameOop" instead.

Right. I got it now. Thanks!

brad

Reply | Threaded
Open this post in threaded view
|

Re: Slang - self primitive: parameters:

Brad Fuller
In reply to this post by Andreas.Raab
Andreas Raab wrote:

> Brad Fuller wrote:
>
>> I've been fooling with this all day.. getting frustrating!
>
>
> If you get frustrated enough and decide to (instead of tricking
> SmartSyntaxPlugin into doing the right thing) do the hard way, here is
> how:
>
> primitiveGetText
>    | text sz oop ptr |
>    self export: true.
>    self var: #text type: 'char*'.
>    self var: #ptr type: 'char*'.
>    text := self cCode: 'GetText()'.
>    sz := self strlen: sz.
>    "Create new String object of appropriate size"
>    oop := interpreterProxy
>              instantiateClass: interpreterProxy classString
>              indexableSize: sz.
>    "Copy data"
>    ptr := interpreterProxy firstIndexableField: oop.
>    self cCode:'memcpy(ptr, text, sz)'.
>    "Return oop"
>    interpreterProxy pop: interpreterProxy methodArgumentCount+1.
>    interpreterProxy push: oop.

Thanks Andreas. I appreciate your help and the more examples I have, the
better I'll understand Slang....the hard way usually results in the easy
way later on. :-)

brad