FFI Plugin | Proposal: Add #doesNotCoerce:for: (like #doesNotUnderstand:)

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

FFI Plugin | Proposal: Add #doesNotCoerce:for: (like #doesNotUnderstand:)

marcel.taeumel
 
Hi all!

We have #doesNotUnderstand:, which is sent to the receiver when a message cannot be understood. Default reaction in Object is to raise MessageNotUnderstood exception.

What if we could have a similar mechanism for FFI calls: #doesNotCoerce:for:. The receiver would be the one that made that call, should be an instance of ExternalLibrary, but could be any object. The arguments would be a pair of (argObject, argType) and the message (like the argument for doesNotUnderstand:) that represents the FFI call.

The pair of (argObject, argType) could be expressed as FFICallArgument:

FFICallArgument
   argObject  ... <Object>
   argType ... <ExternalType>

I suppose that such a new class would have to be reserved in the special objects array. An alternative would be to just use Array. Keep it simple. ;-)

Default reaction could be to implement #doesNotCoerce:for: in Object (as *FFI-Kernel extension) to raise FFICallArgumentNotCoerced exception (to be implemented). Also, we could implement manual coercion in ExternaLibrary to, for example, wrap atomics into their aliasing structures.

ExternalLibrary >> #doesNotCoerce: callArg for: message
   | argObject argType argIndex wrappedArg |
   argObject := callArg first. "or argObject accessor"
   argType := callArg second. "or argType accessor"
   argIndex := message arguments indexOf: argObject.
   wrappedArg := argType referentClass fromHandle: argObject.
   message arguments beWritableObject. "Just in case ;-)"
   message at: argIndex put: wrappedArg.
   ^ message sendTo: self

Please share your thoughts. :-)

Best,
Marcel
Reply | Threaded
Open this post in threaded view
|

Re: FFI Plugin | Proposal: Add #doesNotCoerce:for: (like #doesNotUnderstand:)

marcel.taeumel
 
Hi all, again. :-)

I am aware that such a mechanism would have to be implemented in 2-times-7 different places:


Best,
Marcel

Am 19.06.2020 13:15:40 schrieb Marcel Taeumel <[hidden email]>:

Hi all!

We have #doesNotUnderstand:, which is sent to the receiver when a message cannot be understood. Default reaction in Object is to raise MessageNotUnderstood exception.

What if we could have a similar mechanism for FFI calls: #doesNotCoerce:for:. The receiver would be the one that made that call, should be an instance of ExternalLibrary, but could be any object. The arguments would be a pair of (argObject, argType) and the message (like the argument for doesNotUnderstand:) that represents the FFI call.

The pair of (argObject, argType) could be expressed as FFICallArgument:

FFICallArgument
   argObject  ... <Object>
   argType ... <ExternalType>

I suppose that such a new class would have to be reserved in the special objects array. An alternative would be to just use Array. Keep it simple. ;-)

Default reaction could be to implement #doesNotCoerce:for: in Object (as *FFI-Kernel extension) to raise FFICallArgumentNotCoerced exception (to be implemented). Also, we could implement manual coercion in ExternaLibrary to, for example, wrap atomics into their aliasing structures.

ExternalLibrary >> #doesNotCoerce: callArg for: message
   | argObject argType argIndex wrappedArg |
   argObject := callArg first. "or argObject accessor"
   argType := callArg second. "or argType accessor"
   argIndex := message arguments indexOf: argObject.
   wrappedArg := argType referentClass fromHandle: argObject.
   message arguments beWritableObject. "Just in case ;-)"
   message at: argIndex put: wrappedArg.
   ^ message sendTo: self

Please share your thoughts. :-)

Best,
Marcel
Reply | Threaded
Open this post in threaded view
|

Re: FFI Plugin | Proposal: Add #doesNotCoerce:for: (like #doesNotUnderstand:)

Nicolas Cellier
 
Hi Marcel,
Forget about FFIPlugin it's legacy

I'm currently changing ThreadedFFIPlugin to:
- enable passing ExternalData as atomicType by value
 The use case is the one of ExternalVariable
- enable ExternalData to have an ExternalStructure or ExternalTypeAlias as type inst. var.
 and enable passing that to a corresponding ExternalStructure/ExternalStructure pointer/ExternalTypeAlias/ ExternalTypeAlias pointer
- returning a new ExternalTypeAlias when returning such type by value

This way, we can make FFI a bit safer than using those void *


Le ven. 19 juin 2020 à 13:45, Marcel Taeumel <[hidden email]> a écrit :
 
Hi all, again. :-)

I am aware that such a mechanism would have to be implemented in 2-times-7 different places:


Best,
Marcel

Am 19.06.2020 13:15:40 schrieb Marcel Taeumel <[hidden email]>:

Hi all!

We have #doesNotUnderstand:, which is sent to the receiver when a message cannot be understood. Default reaction in Object is to raise MessageNotUnderstood exception.

What if we could have a similar mechanism for FFI calls: #doesNotCoerce:for:. The receiver would be the one that made that call, should be an instance of ExternalLibrary, but could be any object. The arguments would be a pair of (argObject, argType) and the message (like the argument for doesNotUnderstand:) that represents the FFI call.

The pair of (argObject, argType) could be expressed as FFICallArgument:

FFICallArgument
   argObject  ... <Object>
   argType ... <ExternalType>

I suppose that such a new class would have to be reserved in the special objects array. An alternative would be to just use Array. Keep it simple. ;-)

Default reaction could be to implement #doesNotCoerce:for: in Object (as *FFI-Kernel extension) to raise FFICallArgumentNotCoerced exception (to be implemented). Also, we could implement manual coercion in ExternaLibrary to, for example, wrap atomics into their aliasing structures.

ExternalLibrary >> #doesNotCoerce: callArg for: message
   | argObject argType argIndex wrappedArg |
   argObject := callArg first. "or argObject accessor"
   argType := callArg second. "or argType accessor"
   argIndex := message arguments indexOf: argObject.
   wrappedArg := argType referentClass fromHandle: argObject.
   message arguments beWritableObject. "Just in case ;-)"
   message at: argIndex put: wrappedArg.
   ^ message sendTo: self

Please share your thoughts. :-)

Best,
Marcel
Reply | Threaded
Open this post in threaded view
|

Re: FFI Plugin | Proposal: Add #doesNotCoerce:for: (like #doesNotUnderstand:)

marcel.taeumel
 
Hi Nicolas.

- enable ExternalData to have an ExternalStructure or ExternalTypeAlias as type inst. var.

This does not sound right. But I think you mean that "type" in ExternalData could be a struct type and the plugin would automatically coerce it correctly.

That's good. :-)

"type" in ExternalData must always be an instance of ExternalType.

This way, we can make FFI a bit safer than using those void *

Sounds good.

Best,
Marcel

P.S.: I think I messed up with the name "ExternalTypeAlias". Hmpf. Because is a subclass of ExternalStructure, not ExternalType. Well. :-)

Am 19.06.2020 15:09:01 schrieb Nicolas Cellier <[hidden email]>:

Hi Marcel,
Forget about FFIPlugin it's legacy

I'm currently changing ThreadedFFIPlugin to:
- enable passing ExternalData as atomicType by value
The use case is the one of ExternalVariable
- enable ExternalData to have an ExternalStructure or ExternalTypeAlias as
type inst. var.
and enable passing that to a corresponding
ExternalStructure/ExternalStructure pointer/ExternalTypeAlias/
ExternalTypeAlias pointer
- returning a new ExternalTypeAlias when returning such type by value

This way, we can make FFI a bit safer than using those void *


Le ven. 19 juin 2020 à 13:45, Marcel Taeumel a
écrit :

>
> Hi all, again. :-)
>
> I am aware that such a mechanism would have to be implemented in 2-times-7
> different places:
>
>
> Best,
> Marcel
>
> Am 19.06.2020 13:15:40 schrieb Marcel Taeumel :
> Hi all!
>
> We have #doesNotUnderstand:, which is sent to the receiver when a message
> cannot be understood. Default reaction in Object is to raise
> MessageNotUnderstood exception.
>
> What if we could have a similar mechanism for FFI calls:
> #doesNotCoerce:for:. The receiver would be the one that made that call,
> should be an instance of ExternalLibrary, but could be any object. The
> arguments would be a pair of (argObject, argType) and the message (like the
> argument for doesNotUnderstand:) that represents the FFI call.
>
> The pair of (argObject, argType) could be expressed as FFICallArgument:
>
> FFICallArgument
> argObject ...
> argType ...
>
> I suppose that such a new class would have to be reserved in the special
> objects array. An alternative would be to just use Array. Keep it simple.
> ;-)
>
> Default reaction could be to implement #doesNotCoerce:for: in Object (as
> *FFI-Kernel extension) to raise FFICallArgumentNotCoerced exception (to be
> implemented). Also, we could implement manual coercion in ExternaLibrary
> to, for example, wrap atomics into their aliasing structures.
>
> ExternalLibrary >> #doesNotCoerce: callArg for: message
> | argObject argType argIndex wrappedArg |
> argObject := callArg first. "or argObject accessor"
> argType := callArg second. "or argType accessor"
> argIndex := message arguments indexOf: argObject.
> wrappedArg := argType referentClass fromHandle: argObject.
> message arguments beWritableObject. "Just in case ;-)"
> message at: argIndex put: wrappedArg.
> ^ message sendTo: self
>
> Please share your thoughts. :-)
>
> Best,
> Marcel
>
>
Hi Marcel,
Forget about FFIPlugin it's legacy

I'm currently changing ThreadedFFIPlugin to:
- enable passing ExternalData as atomicType by value
 The use case is the one of ExternalVariable
- enable ExternalData to have an ExternalStructure or ExternalTypeAlias as type inst. var.
 and enable passing that to a corresponding ExternalStructure/ExternalStructure pointer/ExternalTypeAlias/ ExternalTypeAlias pointer
- returning a new ExternalTypeAlias when returning such type by value

This way, we can make FFI a bit safer than using those void *


Le ven. 19 juin 2020 à 13:45, Marcel Taeumel <[hidden email]> a écrit :
 

Hi all, again. :-)

I am aware that such a mechanism would have to be implemented in 2-times-7 different places:


Best,
Marcel

Am 19.06.2020 13:15:40 schrieb Marcel Taeumel <[hidden email]>:

Hi all!

We have #doesNotUnderstand:, which is sent to the receiver when a message cannot be understood. Default reaction in Object is to raise MessageNotUnderstood exception.

What if we could have a similar mechanism for FFI calls: #doesNotCoerce:for:. The receiver would be the one that made that call, should be an instance of ExternalLibrary, but could be any object. The arguments would be a pair of (argObject, argType) and the message (like the argument for doesNotUnderstand:) that represents the FFI call.

The pair of (argObject, argType) could be expressed as FFICallArgument:

FFICallArgument
   argObject  ... <Object>
   argType ... <ExternalType>

I suppose that such a new class would have to be reserved in the special objects array. An alternative would be to just use Array. Keep it simple. ;-)

Default reaction could be to implement #doesNotCoerce:for: in Object (as *FFI-Kernel extension) to raise FFICallArgumentNotCoerced exception (to be implemented). Also, we could implement manual coercion in ExternaLibrary to, for example, wrap atomics into their aliasing structures.

ExternalLibrary >> #doesNotCoerce: callArg for: message
   | argObject argType argIndex wrappedArg |
   argObject := callArg first. "or argObject accessor"
   argType := callArg second. "or argType accessor"
   argIndex := message arguments indexOf: argObject.
   wrappedArg := argType referentClass fromHandle: argObject.
   message arguments beWritableObject. "Just in case ;-)"
   message at: argIndex put: wrappedArg.
   ^ message sendTo: self

Please share your thoughts. :-)

Best,
Marcel


Reply | Threaded
Open this post in threaded view
|

Re: FFI Plugin | Proposal: Add #doesNotCoerce:for: (like #doesNotUnderstand:)

Nicolas Cellier
 


Le ven. 19 juin 2020 à 15:46, Marcel Taeumel <[hidden email]> a écrit :
 
Hi Nicolas.

- enable ExternalData to have an ExternalStructure or ExternalTypeAlias as type inst. var.

This does not sound right. But I think you mean that "type" in ExternalData could be a struct type and the plugin would automatically coerce it correctly.

That's good. :-)

"type" in ExternalData must always be an instance of ExternalType.

I see what you mean.
But, that's not exactly how it works.
ExternalStructureFoo (the class, not an instance) acts as an ExternalType surrogate.
See:
    ExternalType structTypeNamed: #FFISmallStruct1.
It will answer FFISmallStruct1, so FFISmallStruct1 is a type somehow, a structType more exactly (or a type alias).

I suggest to use that as ExternalData type whenever we have a pointer to a FFISmallStruct1 or an array of FFISmallStruct1.
It also make FFI type checking super easy, because we already pass the FFISmallStruct1 as argClass (only when passing struct by value by now, but I suggest extending it when passing FFISmallStruct1 *, which currently is not even possible - we have to declare void *)


This way, we can make FFI a bit safer than using those void *

Sounds good.

Best,
Marcel

P.S.: I think I messed up with the name "ExternalTypeAlias". Hmpf. Because is a subclass of ExternalStructure, not ExternalType. Well. :-)

Am 19.06.2020 15:09:01 schrieb Nicolas Cellier <[hidden email]>:

Hi Marcel,
Forget about FFIPlugin it's legacy

I'm currently changing ThreadedFFIPlugin to:
- enable passing ExternalData as atomicType by value
The use case is the one of ExternalVariable
- enable ExternalData to have an ExternalStructure or ExternalTypeAlias as
type inst. var.
and enable passing that to a corresponding
ExternalStructure/ExternalStructure pointer/ExternalTypeAlias/
ExternalTypeAlias pointer
- returning a new ExternalTypeAlias when returning such type by value

This way, we can make FFI a bit safer than using those void *


Le ven. 19 juin 2020 à 13:45, Marcel Taeumel a
écrit :

>
> Hi all, again. :-)
>
> I am aware that such a mechanism would have to be implemented in 2-times-7
> different places:
>
>
> Best,
> Marcel
>
> Am 19.06.2020 13:15:40 schrieb Marcel Taeumel :
> Hi all!
>
> We have #doesNotUnderstand:, which is sent to the receiver when a message
> cannot be understood. Default reaction in Object is to raise
> MessageNotUnderstood exception.
>
> What if we could have a similar mechanism for FFI calls:
> #doesNotCoerce:for:. The receiver would be the one that made that call,
> should be an instance of ExternalLibrary, but could be any object. The
> arguments would be a pair of (argObject, argType) and the message (like the
> argument for doesNotUnderstand:) that represents the FFI call.
>
> The pair of (argObject, argType) could be expressed as FFICallArgument:
>
> FFICallArgument
> argObject ...
Reply | Threaded
Open this post in threaded view
|

Re: FFI Plugin | Proposal: Add #doesNotCoerce:for: (like #doesNotUnderstand:)

marcel.taeumel
 
Hi Nicolas.

>ExternalStructureFoo (the class, not an instance) acts as an ExternalType
> surrogate.

Well, only by name. Not by object identity.

ExternalType structTypeNamed: #FFISmallStruct1.
> It will answer FFISmallStruct1, so FFISmallStruct1 is a type somehow, a
> structType more exactly (or a type alias).

Well, #structTypeNamed: answers an instance of ExternalType whose referentClass points to the structure class, which is FFISmallStruct in this example.

Yet, the VM / plugin does not care about the name here. It only cares about instances of ExternalType and to which referentClass those types point.

Best,
Marcel

Am 19.06.2020 15:58:59 schrieb Nicolas Cellier <[hidden email]>:

Le ven. 19 juin 2020 à 15:46, Marcel Taeumel a
écrit :

>
> Hi Nicolas.
>
> > - enable ExternalData to have an ExternalStructure or ExternalTypeAlias
> as type inst. var.
>
> This does not sound right. But I think you mean that "type" in
> ExternalData could be a struct type and the plugin would automatically
> coerce it correctly.
>
> That's good. :-)
>
> "type" in ExternalData must always be an instance of ExternalType.
>
> I see what you mean.
But, that's not exactly how it works.
ExternalStructureFoo (the class, not an instance) acts as an ExternalType
surrogate.
See:
ExternalType structTypeNamed: #FFISmallStruct1.
It will answer FFISmallStruct1, so FFISmallStruct1 is a type somehow, a
structType more exactly (or a type alias).

I suggest to use that as ExternalData type whenever we have a pointer to a
FFISmallStruct1 or an array of FFISmallStruct1.
It also make FFI type checking super easy, because we already pass the
FFISmallStruct1 as argClass (only when passing struct by value by now, but
I suggest extending it when passing FFISmallStruct1 *, which currently is
not even possible - we have to declare void *)


> This way, we can make FFI a bit safer than using those void *
>
> Sounds good.
>
> Best,
> Marcel
>
> P.S.: I think I messed up with the name "ExternalTypeAlias". Hmpf. Because
> is a subclass of ExternalStructure, not ExternalType. Well. :-)
>
> Am 19.06.2020 15:09:01 schrieb Nicolas Cellier <>
> [hidden email]>:
> Hi Marcel,
> Forget about FFIPlugin it's legacy
>
> I'm currently changing ThreadedFFIPlugin to:
> - enable passing ExternalData as atomicType by value
> The use case is the one of ExternalVariable
> - enable ExternalData to have an ExternalStructure or ExternalTypeAlias as
> type inst. var.
> and enable passing that to a corresponding
> ExternalStructure/ExternalStructure pointer/ExternalTypeAlias/
> ExternalTypeAlias pointer
> - returning a new ExternalTypeAlias when returning such type by value
>
> This way, we can make FFI a bit safer than using those void *
>
>
> Le ven. 19 juin 2020 à 13:45, Marcel Taeumel a
> écrit :
>
> >
> > Hi all, again. :-)
> >
> > I am aware that such a mechanism would have to be implemented in
> 2-times-7
> > different places:
> >
> >
> > Best,
> > Marcel
> >
> > Am 19.06.2020 13:15:40 schrieb Marcel Taeumel :
> > Hi all!
> >
> > We have #doesNotUnderstand:, which is sent to the receiver when a
> message
> > cannot be understood. Default reaction in Object is to raise
> > MessageNotUnderstood exception.
> >
> > What if we could have a similar mechanism for FFI calls:
> > #doesNotCoerce:for:. The receiver would be the one that made that call,
> > should be an instance of ExternalLibrary, but could be any object. The
> > arguments would be a pair of (argObject, argType) and the message (like
> the
> > argument for doesNotUnderstand:) that represents the FFI call.
> >
> > The pair of (argObject, argType) could be expressed as FFICallArgument:
> >
> > FFICallArgument
> > argObject ...
>
>


Le ven. 19 juin 2020 à 15:46, Marcel Taeumel <[hidden email]> a écrit :
 






Hi Nicolas.

- enable ExternalData to have an ExternalStructure or ExternalTypeAlias as type inst. var.

This does not sound right. But I think you mean that "type" in ExternalData could be a struct type and the plugin would automatically coerce it correctly.

That's good. :-)

"type" in ExternalData must always be an instance of ExternalType.

I see what you mean.
But, that's not exactly how it works.
ExternalStructureFoo (the class, not an instance) acts as an ExternalType surrogate.
See:
    ExternalType structTypeNamed: #FFISmallStruct1.
It will answer FFISmallStruct1, so FFISmallStruct1 is a type somehow, a structType more exactly (or a type alias).

I suggest to use that as ExternalData type whenever we have a pointer to a FFISmallStruct1 or an array of FFISmallStruct1.
It also make FFI type checking super easy, because we already pass the FFISmallStruct1 as argClass (only when passing struct by value by now, but I suggest extending it when passing FFISmallStruct1 *, which currently is not even possible - we have to declare void *)


This way, we can make FFI a bit safer than using those void *

Sounds good.

Best,
Marcel

P.S.: I think I messed up with the name "ExternalTypeAlias". Hmpf. Because is a subclass of ExternalStructure, not ExternalType. Well. :-)



Am 19.06.2020 15:09:01 schrieb Nicolas Cellier <[hidden email]>:

Hi Marcel,

Forget about FFIPlugin it's legacy



I'm currently changing ThreadedFFIPlugin to:

- enable passing ExternalData as atomicType by value

The use case is the one of ExternalVariable

- enable ExternalData to have an ExternalStructure or ExternalTypeAlias as

type inst. var.

and enable passing that to a corresponding

ExternalStructure/ExternalStructure pointer/ExternalTypeAlias/

ExternalTypeAlias pointer

- returning a new ExternalTypeAlias when returning such type by value



This way, we can make FFI a bit safer than using those void *





Le ven. 19 juin 2020 à 13:45, Marcel Taeumel a

écrit :



>

> Hi all, again. :-)

>

> I am aware that such a mechanism would have to be implemented in 2-times-7

> different places:

>

>

> Best,

> Marcel

>

> Am 19.06.2020 13:15:40 schrieb Marcel Taeumel :

> Hi all!

>

> We have #doesNotUnderstand:, which is sent to the receiver when a message

> cannot be understood. Default reaction in Object is to raise

> MessageNotUnderstood exception.

>

> What if we could have a similar mechanism for FFI calls:

> #doesNotCoerce:for:. The receiver would be the one that made that call,

> should be an instance of ExternalLibrary, but could be any object. The

> arguments would be a pair of (argObject, argType) and the message (like the

> argument for doesNotUnderstand:) that represents the FFI call.

>

> The pair of (argObject, argType) could be expressed as FFICallArgument:

>

> FFICallArgument

> argObject ...

Reply | Threaded
Open this post in threaded view
|

Re: FFI Plugin | Proposal: Add #doesNotCoerce:for: (like #doesNotUnderstand:)

marcel.taeumel
 
Maybe this helps:

FFISmallStruct1 externalType ~~ FFISmallStruct1.
FFISmallStruct1 externalType == (ExternalType structTypeNamed: FFISmallStruct1 className).
FFISmallStruct1 externalType referentClass == FFISmallStruct1.

FFISmallStruct1 new isKindOf: ExternalStructure.
FFISmallStruct1 externalType isKindOf: ExternalType.

ExternalTypeAlias inheritsFrom: ExternalStructure. "!!!"

Best,
Marcel

Am 19.06.2020 16:01:53 schrieb Marcel Taeumel <[hidden email]>:

Hi Nicolas.

>ExternalStructureFoo (the class, not an instance) acts as an ExternalType
> surrogate.

Well, only by name. Not by object identity.

ExternalType structTypeNamed: #FFISmallStruct1.
> It will answer FFISmallStruct1, so FFISmallStruct1 is a type somehow, a
> structType more exactly (or a type alias).

Well, #structTypeNamed: answers an instance of ExternalType whose referentClass points to the structure class, which is FFISmallStruct in this example.

Yet, the VM / plugin does not care about the name here. It only cares about instances of ExternalType and to which referentClass those types point.

Best,
Marcel

Am 19.06.2020 15:58:59 schrieb Nicolas Cellier <[hidden email]>:

Le ven. 19 juin 2020 à 15:46, Marcel Taeumel a
écrit :

>
> Hi Nicolas.
>
> > - enable ExternalData to have an ExternalStructure or ExternalTypeAlias
> as type inst. var.
>
> This does not sound right. But I think you mean that "type" in
> ExternalData could be a struct type and the plugin would automatically
> coerce it correctly.
>
> That's good. :-)
>
> "type" in ExternalData must always be an instance of ExternalType.
>
> I see what you mean.
But, that's not exactly how it works.
ExternalStructureFoo (the class, not an instance) acts as an ExternalType
surrogate.
See:
ExternalType structTypeNamed: #FFISmallStruct1.
It will answer FFISmallStruct1, so FFISmallStruct1 is a type somehow, a
structType more exactly (or a type alias).

I suggest to use that as ExternalData type whenever we have a pointer to a
FFISmallStruct1 or an array of FFISmallStruct1.
It also make FFI type checking super easy, because we already pass the
FFISmallStruct1 as argClass (only when passing struct by value by now, but
I suggest extending it when passing FFISmallStruct1 *, which currently is
not even possible - we have to declare void *)


> This way, we can make FFI a bit safer than using those void *
>
> Sounds good.
>
> Best,
> Marcel
>
> P.S.: I think I messed up with the name "ExternalTypeAlias". Hmpf. Because
> is a subclass of ExternalStructure, not ExternalType. Well. :-)
>
> Am 19.06.2020 15:09:01 schrieb Nicolas Cellier <>
> [hidden email]>:
> Hi Marcel,
> Forget about FFIPlugin it's legacy
>
> I'm currently changing ThreadedFFIPlugin to:
> - enable passing ExternalData as atomicType by value
> The use case is the one of ExternalVariable
> - enable ExternalData to have an ExternalStructure or ExternalTypeAlias as
> type inst. var.
> and enable passing that to a corresponding
> ExternalStructure/ExternalStructure pointer/ExternalTypeAlias/
> ExternalTypeAlias pointer
> - returning a new ExternalTypeAlias when returning such type by value
>
> This way, we can make FFI a bit safer than using those void *
>
>
> Le ven. 19 juin 2020 à 13:45, Marcel Taeumel a
> écrit :
>
> >
> > Hi all, again. :-)
> >
> > I am aware that such a mechanism would have to be implemented in
> 2-times-7
> > different places:
> >
> >
> > Best,
> > Marcel
> >
> > Am 19.06.2020 13:15:40 schrieb Marcel Taeumel :
> > Hi all!
> >
> > We have #doesNotUnderstand:, which is sent to the receiver when a
> message
> > cannot be understood. Default reaction in Object is to raise
> > MessageNotUnderstood exception.
> >
> > What if we could have a similar mechanism for FFI calls:
> > #doesNotCoerce:for:. The receiver would be the one that made that call,
> > should be an instance of ExternalLibrary, but could be any object. The
> > arguments would be a pair of (argObject, argType) and the message (like
> the
> > argument for doesNotUnderstand:) that represents the FFI call.
> >
> > The pair of (argObject, argType) could be expressed as FFICallArgument:
> >
> > FFICallArgument
> > argObject ...
>
>


Le ven. 19 juin 2020 à 15:46, Marcel Taeumel <[hidden email]> a écrit :
 






Hi Nicolas.

- enable ExternalData to have an ExternalStructure or ExternalTypeAlias as type inst. var.

This does not sound right. But I think you mean that "type" in ExternalData could be a struct type and the plugin would automatically coerce it correctly.

That's good. :-)

"type" in ExternalData must always be an instance of ExternalType.

I see what you mean.
But, that's not exactly how it works.
ExternalStructureFoo (the class, not an instance) acts as an ExternalType surrogate.
See:
    ExternalType structTypeNamed: #FFISmallStruct1.
It will answer FFISmallStruct1, so FFISmallStruct1 is a type somehow, a structType more exactly (or a type alias).

I suggest to use that as ExternalData type whenever we have a pointer to a FFISmallStruct1 or an array of FFISmallStruct1.
It also make FFI type checking super easy, because we already pass the FFISmallStruct1 as argClass (only when passing struct by value by now, but I suggest extending it when passing FFISmallStruct1 *, which currently is not even possible - we have to declare void *)


This way, we can make FFI a bit safer than using those void *

Sounds good.

Best,
Marcel

P.S.: I think I messed up with the name "ExternalTypeAlias". Hmpf. Because is a subclass of ExternalStructure, not ExternalType. Well. :-)



Am 19.06.2020 15:09:01 schrieb Nicolas Cellier <[hidden email]>:

Hi Marcel,

Forget about FFIPlugin it's legacy



I'm currently changing ThreadedFFIPlugin to:

- enable passing ExternalData as atomicType by value

The use case is the one of ExternalVariable

- enable ExternalData to have an ExternalStructure or ExternalTypeAlias as

type inst. var.

and enable passing that to a corresponding

ExternalStructure/ExternalStructure pointer/ExternalTypeAlias/

ExternalTypeAlias pointer

- returning a new ExternalTypeAlias when returning such type by value



This way, we can make FFI a bit safer than using those void *





Le ven. 19 juin 2020 à 13:45, Marcel Taeumel a

écrit :



>

> Hi all, again. :-)

>

> I am aware that such a mechanism would have to be implemented in 2-times-7

> different places:

>

>

> Best,

> Marcel

>

> Am 19.06.2020 13:15:40 schrieb Marcel Taeumel :

> Hi all!

>

> We have #doesNotUnderstand:, which is sent to the receiver when a message

> cannot be understood. Default reaction in Object is to raise

> MessageNotUnderstood exception.

>

> What if we could have a similar mechanism for FFI calls:

> #doesNotCoerce:for:. The receiver would be the one that made that call,

> should be an instance of ExternalLibrary, but could be any object. The

> arguments would be a pair of (argObject, argType) and the message (like the

> argument for doesNotUnderstand:) that represents the FFI call.

>

> The pair of (argObject, argType) could be expressed as FFICallArgument:

>

> FFICallArgument

> argObject ...

Reply | Threaded
Open this post in threaded view
|

Re: FFI Plugin | Proposal: Add #doesNotCoerce:for: (like #doesNotUnderstand:)

marcel.taeumel
In reply to this post by marcel.taeumel
 
Hi all!

What would be the "best English" for such a mechanism?

anExternalLibrary doesNotCoerce: aCallArg for: aMessage.
anExternalLibrary doesNotCoerce: aCallArg in: aMessage.
anExternalLibrary cannotCoerce: aCallArg for: aMessage.
anExternalLibrary cannotCoerce: aCallArg in: aMessage.
...

Best,
Marcel

Am 19.06.2020 15:46:30 schrieb Marcel Taeumel <[hidden email]>:

Hi Nicolas.

- enable ExternalData to have an ExternalStructure or ExternalTypeAlias as type inst. var.

This does not sound right. But I think you mean that "type" in ExternalData could be a struct type and the plugin would automatically coerce it correctly.

That's good. :-)

"type" in ExternalData must always be an instance of ExternalType.

This way, we can make FFI a bit safer than using those void *

Sounds good.

Best,
Marcel

P.S.: I think I messed up with the name "ExternalTypeAlias". Hmpf. Because is a subclass of ExternalStructure, not ExternalType. Well. :-)

Am 19.06.2020 15:09:01 schrieb Nicolas Cellier <[hidden email]>:

Hi Marcel,
Forget about FFIPlugin it's legacy

I'm currently changing ThreadedFFIPlugin to:
- enable passing ExternalData as atomicType by value
The use case is the one of ExternalVariable
- enable ExternalData to have an ExternalStructure or ExternalTypeAlias as
type inst. var.
and enable passing that to a corresponding
ExternalStructure/ExternalStructure pointer/ExternalTypeAlias/
ExternalTypeAlias pointer
- returning a new ExternalTypeAlias when returning such type by value

This way, we can make FFI a bit safer than using those void *


Le ven. 19 juin 2020 à 13:45, Marcel Taeumel a
écrit :

>
> Hi all, again. :-)
>
> I am aware that such a mechanism would have to be implemented in 2-times-7
> different places:
>
>
> Best,
> Marcel
>
> Am 19.06.2020 13:15:40 schrieb Marcel Taeumel :
> Hi all!
>
> We have #doesNotUnderstand:, which is sent to the receiver when a message
> cannot be understood. Default reaction in Object is to raise
> MessageNotUnderstood exception.
>
> What if we could have a similar mechanism for FFI calls:
> #doesNotCoerce:for:. The receiver would be the one that made that call,
> should be an instance of ExternalLibrary, but could be any object. The
> arguments would be a pair of (argObject, argType) and the message (like the
> argument for doesNotUnderstand:) that represents the FFI call.
>
> The pair of (argObject, argType) could be expressed as FFICallArgument:
>
> FFICallArgument
> argObject ...
> argType ...
>
> I suppose that such a new class would have to be reserved in the special
> objects array. An alternative would be to just use Array. Keep it simple.
> ;-)
>
> Default reaction could be to implement #doesNotCoerce:for: in Object (as
> *FFI-Kernel extension) to raise FFICallArgumentNotCoerced exception (to be
> implemented). Also, we could implement manual coercion in ExternaLibrary
> to, for example, wrap atomics into their aliasing structures.
>
> ExternalLibrary >> #doesNotCoerce: callArg for: message
> | argObject argType argIndex wrappedArg |
> argObject := callArg first. "or argObject accessor"
> argType := callArg second. "or argType accessor"
> argIndex := message arguments indexOf: argObject.
> wrappedArg := argType referentClass fromHandle: argObject.
> message arguments beWritableObject. "Just in case ;-)"
> message at: argIndex put: wrappedArg.
> ^ message sendTo: self
>
> Please share your thoughts. :-)
>
> Best,
> Marcel
>
>
Hi Marcel,
Forget about FFIPlugin it's legacy

I'm currently changing ThreadedFFIPlugin to:
- enable passing ExternalData as atomicType by value
 The use case is the one of ExternalVariable
- enable ExternalData to have an ExternalStructure or ExternalTypeAlias as type inst. var.
 and enable passing that to a corresponding ExternalStructure/ExternalStructure pointer/ExternalTypeAlias/ ExternalTypeAlias pointer
- returning a new ExternalTypeAlias when returning such type by value

This way, we can make FFI a bit safer than using those void *


Le ven. 19 juin 2020 à 13:45, Marcel Taeumel <[hidden email]> a écrit :
 

Hi all, again. :-)

I am aware that such a mechanism would have to be implemented in 2-times-7 different places:


Best,
Marcel

Am 19.06.2020 13:15:40 schrieb Marcel Taeumel <[hidden email]>:

Hi all!

We have #doesNotUnderstand:, which is sent to the receiver when a message cannot be understood. Default reaction in Object is to raise MessageNotUnderstood exception.

What if we could have a similar mechanism for FFI calls: #doesNotCoerce:for:. The receiver would be the one that made that call, should be an instance of ExternalLibrary, but could be any object. The arguments would be a pair of (argObject, argType) and the message (like the argument for doesNotUnderstand:) that represents the FFI call.

The pair of (argObject, argType) could be expressed as FFICallArgument:

FFICallArgument
   argObject  ... <Object>
   argType ... <ExternalType>

I suppose that such a new class would have to be reserved in the special objects array. An alternative would be to just use Array. Keep it simple. ;-)

Default reaction could be to implement #doesNotCoerce:for: in Object (as *FFI-Kernel extension) to raise FFICallArgumentNotCoerced exception (to be implemented). Also, we could implement manual coercion in ExternaLibrary to, for example, wrap atomics into their aliasing structures.

ExternalLibrary >> #doesNotCoerce: callArg for: message
   | argObject argType argIndex wrappedArg |
   argObject := callArg first. "or argObject accessor"
   argType := callArg second. "or argType accessor"
   argIndex := message arguments indexOf: argObject.
   wrappedArg := argType referentClass fromHandle: argObject.
   message arguments beWritableObject. "Just in case ;-)"
   message at: argIndex put: wrappedArg.
   ^ message sendTo: self

Please share your thoughts. :-)

Best,
Marcel


Reply | Threaded
Open this post in threaded view
|

Re: FFI Plugin | Proposal: Add #doesNotCoerce:for: (like #doesNotUnderstand:)

Nicolas Cellier
In reply to this post by marcel.taeumel
 


Le ven. 19 juin 2020 à 16:02, Marcel Taeumel <[hidden email]> a écrit :
 
Hi Nicolas.

>ExternalStructureFoo (the class, not an instance) acts as an ExternalType
> surrogate.

Well, only by name. Not by object identity.

ExternalType structTypeNamed: #FFISmallStruct1.
> It will answer FFISmallStruct1, so FFISmallStruct1 is a type somehow, a
> structType more exactly (or a type alias).

Well, #structTypeNamed: answers an instance of ExternalType whose referentClass points to the structure class, which is FFISmallStruct in this example.


Ah sorry, my mistake.
I indeed need to go thru referentClass to achieve what I was thinking of.
Thanks!
 
Yet, the VM / plugin does not care about the name here. It only cares about instances of ExternalType and to which referentClass those types point.
Since we pass argClass, we can simply check against ExternalData type referentClass.

Best,
Marcel

Am 19.06.2020 15:58:59 schrieb Nicolas Cellier <[hidden email]>:

Le ven. 19 juin 2020 à 15:46, Marcel Taeumel a
écrit :

>
> Hi Nicolas.
>
> > - enable ExternalData to have an ExternalStructure or ExternalTypeAlias
> as type inst. var.
>
> This does not sound right. But I think you mean that "type" in
> ExternalData could be a struct type and the plugin would automatically
> coerce it correctly.
>
> That's good. :-)
>
> "type" in ExternalData must always be an instance of ExternalType.
>
> I see what you mean.
But, that's not exactly how it works.
ExternalStructureFoo (the class, not an instance) acts as an ExternalType
surrogate.
See:
ExternalType structTypeNamed: #FFISmallStruct1.
It will answer FFISmallStruct1, so FFISmallStruct1 is a type somehow, a
structType more exactly (or a type alias).

I suggest to use that as ExternalData type whenever we have a pointer to a
FFISmallStruct1 or an array of FFISmallStruct1.
It also make FFI type checking super easy, because we already pass the
FFISmallStruct1 as argClass (only when passing struct by value by now, but
I suggest extending it when passing FFISmallStruct1 *, which currently is
not even possible - we have to declare void *)


> This way, we can make FFI a bit safer than using those void *
>
> Sounds good.
>
> Best,
> Marcel
>
> P.S.: I think I messed up with the name "ExternalTypeAlias". Hmpf. Because
> is a subclass of ExternalStructure, not ExternalType. Well. :-)
>
> Am 19.06.2020 15:09:01 schrieb Nicolas Cellier <>
> [hidden email]>:
> Hi Marcel,
> Forget about FFIPlugin it's legacy
>
> I'm currently changing ThreadedFFIPlugin to:
> - enable passing ExternalData as atomicType by value
> The use case is the one of ExternalVariable
> - enable ExternalData to have an ExternalStructure or ExternalTypeAlias as
> type inst. var.
> and enable passing that to a corresponding
> ExternalStructure/ExternalStructure pointer/ExternalTypeAlias/
> ExternalTypeAlias pointer
> - returning a new ExternalTypeAlias when returning such type by value
>
> This way, we can make FFI a bit safer than using those void *
>
>
> Le ven. 19 juin 2020 à 13:45, Marcel Taeumel a
> écrit :
>
> >
> > Hi all, again. :-)
> >
> > I am aware that such a mechanism would have to be implemented in
> 2-times-7
> > different places:
> >
> >
> > Best,
> > Marcel
> >
> > Am 19.06.2020 13:15:40 schrieb Marcel Taeumel :
> > Hi all!
> >
> > We have #doesNotUnderstand:, which is sent to the receiver when a
> message
> > cannot be understood. Default reaction in Object is to raise
> > MessageNotUnderstood exception.
> >
> > What if we could have a similar mechanism for FFI calls:
> > #doesNotCoerce:for:. The receiver would be the one that made that call,
> > should be an instance of ExternalLibrary, but could be any object. The
> > arguments would be a pair of (argObject, argType) and the message (like
> the
> > argument for doesNotUnderstand:) that represents the FFI call.
> >
> > The pair of (argObject, argType) could be expressed as FFICallArgument:
> >
> > FFICallArgument
> > argObject ...
>
>


Le ven. 19 juin 2020 à 15:46, Marcel Taeumel <[hidden email]> a écrit :
 






Hi Nicolas.

- enable ExternalData to have an ExternalStructure or ExternalTypeAlias as type inst. var.

This does not sound right. But I think you mean that "type" in ExternalData could be a struct type and the plugin would automatically coerce it correctly.

That's good. :-)

"type" in ExternalData must always be an instance of ExternalType.

I see what you mean.
But, that's not exactly how it works.
ExternalStructureFoo (the class, not an instance) acts as an ExternalType surrogate.
See:
    ExternalType structTypeNamed: #FFISmallStruct1.
It will answer FFISmallStruct1, so FFISmallStruct1 is a type somehow, a structType more exactly (or a type alias).

I suggest to use that as ExternalData type whenever we have a pointer to a FFISmallStruct1 or an array of FFISmallStruct1.
It also make FFI type checking super easy, because we already pass the FFISmallStruct1 as argClass (only when passing struct by value by now, but I suggest extending it when passing FFISmallStruct1 *, which currently is not even possible - we have to declare void *)


This way, we can make FFI a bit safer than using those void *

Sounds good.

Best,
Marcel

P.S.: I think I messed up with the name "ExternalTypeAlias". Hmpf. Because is a subclass of ExternalStructure, not ExternalType. Well. :-)



Am 19.06.2020 15:09:01 schrieb Nicolas Cellier <[hidden email]>:

Hi Marcel,

Forget about FFIPlugin it's legacy



I'm currently changing ThreadedFFIPlugin to:

- enable passing ExternalData as atomicType by value

The use case is the one of ExternalVariable

- enable ExternalData to have an ExternalStructure or ExternalTypeAlias as

type inst. var.

and enable passing that to a corresponding

ExternalStructure/ExternalStructure pointer/ExternalTypeAlias/

ExternalTypeAlias pointer

- returning a new ExternalTypeAlias when returning such type by value



This way, we can make FFI a bit safer than using those void *





Le ven. 19 juin 2020 à 13:45, Marcel Taeumel a

écrit :



>

> Hi all, again. :-)

>

> I am aware that such a mechanism would have to be implemented in 2-times-7

> different places:

>

>

> Best,

> Marcel

>

> Am 19.06.2020 13:15:40 schrieb Marcel Taeumel :

> Hi all!

>

> We have #doesNotUnderstand:, which is sent to the receiver when a message

> cannot be understood. Default reaction in Object is to raise

> MessageNotUnderstood exception.

>

> What if we could have a similar mechanism for FFI calls:

> #doesNotCoerce:for:. The receiver would be the one that made that call,

> should be an instance of ExternalLibrary, but could be any object. The

> arguments would be a pair of (argObject, argType) and the message (like the

> argument for doesNotUnderstand:) that represents the FFI call.

>

> The pair of (argObject, argType) could be expressed as FFICallArgument:

>

> FFICallArgument

> argObject ...

Reply | Threaded
Open this post in threaded view
|

Re: FFI Plugin | Proposal: Add #doesNotCoerce:for: (like #doesNotUnderstand:)

fniephaus
In reply to this post by marcel.taeumel
 
Hi Marcel:

On Fri, 19 Jun 2020 at 1:15 pm, Marcel Taeumel <[hidden email]> wrote:
 
Hi all!

We have #doesNotUnderstand:, which is sent to the receiver when a message cannot be understood. Default reaction in Object is to raise MessageNotUnderstood exception.

What if we could have a similar mechanism for FFI calls: #doesNotCoerce:for:. The receiver would be the one that made that call, should be an instance of ExternalLibrary, but could be any object. The arguments would be a pair of (argObject, argType) and the message (like the argument for doesNotUnderstand:) that represents the FFI call.

I don't like the idea of adding a plugin-specific mechanism like this to the VM. I know it's not as convenient, but maybe something similar can be achieved with error codes in fallback code? There already is BAD_ARGUMENT, maybe there's a way to encode which argument is bad in the error code?

Fabio


The pair of (argObject, argType) could be expressed as FFICallArgument:

FFICallArgument
   argObject  ... <Object>
   argType ... <ExternalType>

I suppose that such a new class would have to be reserved in the special objects array. An alternative would be to just use Array. Keep it simple. ;-)

Default reaction could be to implement #doesNotCoerce:for: in Object (as *FFI-Kernel extension) to raise FFICallArgumentNotCoerced exception (to be implemented). Also, we could implement manual coercion in ExternaLibrary to, for example, wrap atomics into their aliasing structures.

ExternalLibrary >> #doesNotCoerce: callArg for: message
   | argObject argType argIndex wrappedArg |
   argObject := callArg first. "or argObject accessor"
   argType := callArg second. "or argType accessor"
   argIndex := message arguments indexOf: argObject.
   wrappedArg := argType referentClass fromHandle: argObject.
   message arguments beWritableObject. "Just in case ;-)"
   message at: argIndex put: wrappedArg.
   ^ message sendTo: self

Please share your thoughts. :-)

Best,
Marcel
Reply | Threaded
Open this post in threaded view
|

Re: FFI Plugin | Proposal: Add #doesNotCoerce:for: (like #doesNotUnderstand:)

marcel.taeumel
 
Hi Fabio,

I don't like the idea of adding a plugin-specific mechanism like this to the VM.

Why is that? The implementation strategy would be very clear: like #doesNotUnderstand:. It's just a new entry on the special objects array.

There already is BAD_ARGUMENT, maybe there's a way to encode which argument is bad in the error code?

That wouldn't be any better. We could not support on-the-fly packaging of arguments for FFI calls by relying on just the error code. Without on-the-fly packaging, the FFI call could likely be unsafe (e.g. everybody using 'int' instead of the enum type as proposed in the library) or awkward to program (e.g., Alien callbacks require Smalltalk blocks to be warpped into Callback objects).

Best,
Marcel

Am 20.06.2020 22:05:29 schrieb Fabio Niephaus <[hidden email]>:

Hi Marcel:

On Fri, 19 Jun 2020 at 1:15 pm, Marcel Taeumel
wrote:

>
> Hi all!
>
> We have #doesNotUnderstand:, which is sent to the receiver when a message
> cannot be understood. Default reaction in Object is to raise
> MessageNotUnderstood exception.
>
> What if we could have a similar mechanism for FFI calls:
> #doesNotCoerce:for:. The receiver would be the one that made that call,
> should be an instance of ExternalLibrary, but could be any object. The
> arguments would be a pair of (argObject, argType) and the message (like the
> argument for doesNotUnderstand:) that represents the FFI call.
>

I don't like the idea of adding a plugin-specific mechanism like this to
the VM. I know it's not as convenient, but maybe something similar can be
achieved with error codes in fallback code? There already is BAD_ARGUMENT,
maybe there's a way to encode which argument is bad in the error code?

Fabio


> The pair of (argObject, argType) could be expressed as FFICallArgument:
>
> FFICallArgument
> argObject ...
> argType ...
>
> I suppose that such a new class would have to be reserved in the special
> objects array. An alternative would be to just use Array. Keep it simple.
> ;-)
>
> Default reaction could be to implement #doesNotCoerce:for: in Object (as
> *FFI-Kernel extension) to raise FFICallArgumentNotCoerced exception (to be
> implemented). Also, we could implement manual coercion in ExternaLibrary
> to, for example, wrap atomics into their aliasing structures.
>
> ExternalLibrary >> #doesNotCoerce: callArg for: message
> | argObject argType argIndex wrappedArg |
> argObject := callArg first. "or argObject accessor"
> argType := callArg second. "or argType accessor"
> argIndex := message arguments indexOf: argObject.
> wrappedArg := argType referentClass fromHandle: argObject.
> message arguments beWritableObject. "Just in case ;-)"
> message at: argIndex put: wrappedArg.
> ^ message sendTo: self
>
> Please share your thoughts. :-)
>
> Best,
> Marcel
>
Hi Marcel:

On Fri, 19 Jun 2020 at 1:15 pm, Marcel Taeumel <[hidden email]> wrote:
 
Hi all!

We have #doesNotUnderstand:, which is sent to the receiver when a message cannot be understood. Default reaction in Object is to raise MessageNotUnderstood exception.

What if we could have a similar mechanism for FFI calls: #doesNotCoerce:for:. The receiver would be the one that made that call, should be an instance of ExternalLibrary, but could be any object. The arguments would be a pair of (argObject, argType) and the message (like the argument for doesNotUnderstand:) that represents the FFI call.

I don't like the idea of adding a plugin-specific mechanism like this to the VM. I know it's not as convenient, but maybe something similar can be achieved with error codes in fallback code? There already is BAD_ARGUMENT, maybe there's a way to encode which argument is bad in the error code?

Fabio


The pair of (argObject, argType) could be expressed as FFICallArgument:

FFICallArgument
   argObject  ... <Object>
   argType ... <ExternalType>

I suppose that such a new class would have to be reserved in the special objects array. An alternative would be to just use Array. Keep it simple. ;-)

Default reaction could be to implement #doesNotCoerce:for: in Object (as *FFI-Kernel extension) to raise FFICallArgumentNotCoerced exception (to be implemented). Also, we could implement manual coercion in ExternaLibrary to, for example, wrap atomics into their aliasing structures.

ExternalLibrary >> #doesNotCoerce: callArg for: message
   | argObject argType argIndex wrappedArg |
   argObject := callArg first. "or argObject accessor"
   argType := callArg second. "or argType accessor"
   argIndex := message arguments indexOf: argObject.
   wrappedArg := argType referentClass fromHandle: argObject.
   message arguments beWritableObject. "Just in case ;-)"
   message at: argIndex put: wrappedArg.
   ^ message sendTo: self

Please share your thoughts. :-)

Best,
Marcel

Reply | Threaded
Open this post in threaded view
|

Re: FFI Plugin | Proposal: Add #doesNotCoerce:for: (like #doesNotUnderstand:)

fniephaus
 
On Mon, Jun 22, 2020 at 9:44 AM Marcel Taeumel <[hidden email]> wrote:
>
>
> Hi Fabio,
>
> > I don't like the idea of adding a plugin-specific mechanism like this to the VM.
>
> Why is that? The implementation strategy would be very clear: like #doesNotUnderstand:. It's just a new entry on the special objects array.

There are very few mechanisms like this (aboutToReturn,
cannotInterpret, mustBeBoolean, ...), none of them are
plugin-specific. I'd also prefer to keep the number of special objects
as small as possible, the FFIPlugin already reserves quite many of
them.

>
> > There already is BAD_ARGUMENT, maybe there's a way to encode which argument is bad in the error code?
>
> That wouldn't be any better. We could not support on-the-fly packaging of arguments for FFI calls by relying on just the error code. Without on-the-fly packaging, the FFI call could likely be unsafe (e.g. everybody using 'int' instead of the enum type as proposed in the library) or awkward to program (e.g., Alien callbacks require Smalltalk blocks to be warpped into Callback objects).

More importantly, I don't think this type of automatic conversion
should be part of the FFIPlugin, I'd much rather see it being built on
top of the existing infrastructure. Why can't there be a mechanism
that looks at the FFI call in question and converts arguments before
executing it?

Fabio

>
> Best,
> Marcel
>
> Am 20.06.2020 22:05:29 schrieb Fabio Niephaus <[hidden email]>:
>
> Hi Marcel:
>
> On Fri, 19 Jun 2020 at 1:15 pm, Marcel Taeumel
> wrote:
>
> >
> > Hi all!
> >
> > We have #doesNotUnderstand:, which is sent to the receiver when a message
> > cannot be understood. Default reaction in Object is to raise
> > MessageNotUnderstood exception.
> >
> > What if we could have a similar mechanism for FFI calls:
> > #doesNotCoerce:for:. The receiver would be the one that made that call,
> > should be an instance of ExternalLibrary, but could be any object. The
> > arguments would be a pair of (argObject, argType) and the message (like the
> > argument for doesNotUnderstand:) that represents the FFI call.
> >
>
> I don't like the idea of adding a plugin-specific mechanism like this to
> the VM. I know it's not as convenient, but maybe something similar can be
> achieved with error codes in fallback code? There already is BAD_ARGUMENT,
> maybe there's a way to encode which argument is bad in the error code?
>
> Fabio
>
>
> > The pair of (argObject, argType) could be expressed as FFICallArgument:
> >
> > FFICallArgument
> > argObject ...
Reply | Threaded
Open this post in threaded view
|

Re: FFI Plugin | Proposal: Add #doesNotCoerce:for: (like #doesNotUnderstand:)

Nicolas Cellier
 


Le lun. 22 juin 2020 à 12:47, Fabio Niephaus <[hidden email]> a écrit :
 
On Mon, Jun 22, 2020 at 9:44 AM Marcel Taeumel <[hidden email]> wrote:
>
>
> Hi Fabio,
>
> > I don't like the idea of adding a plugin-specific mechanism like this to the VM.
>
> Why is that? The implementation strategy would be very clear: like #doesNotUnderstand:. It's just a new entry on the special objects array.

There are very few mechanisms like this (aboutToReturn,
cannotInterpret, mustBeBoolean, ...), none of them are
plugin-specific. I'd also prefer to keep the number of special objects
as small as possible, the FFIPlugin already reserves quite many of
them.

>
> > There already is BAD_ARGUMENT, maybe there's a way to encode which argument is bad in the error code?
>
> That wouldn't be any better. We could not support on-the-fly packaging of arguments for FFI calls by relying on just the error code. Without on-the-fly packaging, the FFI call could likely be unsafe (e.g. everybody using 'int' instead of the enum type as proposed in the library) or awkward to program (e.g., Alien callbacks require Smalltalk blocks to be warpped into Callback objects).

More importantly, I don't think this type of automatic conversion
should be part of the FFIPlugin, I'd much rather see it being built on
top of the existing infrastructure. Why can't there be a mechanism
that looks at the FFI call in question and converts arguments before
executing it?

Fabio

Exactly, that's how UFFI works.
Easier to handle error, easier to handle automatic coercion or other application specific hook.
While implementing HDF5, I've patched DLLCC in VW too: the key is to use double dispatching on parameter type specification and actual argument class, instead of large sequences of if (like we find in our plugin). This way, I can marshall my application specific data at will.

>
> Best,
> Marcel
>
> Am 20.06.2020 22:05:29 schrieb Fabio Niephaus <[hidden email]>:
>
> Hi Marcel:
>
> On Fri, 19 Jun 2020 at 1:15 pm, Marcel Taeumel
> wrote:
>
> >
> > Hi all!
> >
> > We have #doesNotUnderstand:, which is sent to the receiver when a message
> > cannot be understood. Default reaction in Object is to raise
> > MessageNotUnderstood exception.
> >
> > What if we could have a similar mechanism for FFI calls:
> > #doesNotCoerce:for:. The receiver would be the one that made that call,
> > should be an instance of ExternalLibrary, but could be any object. The
> > arguments would be a pair of (argObject, argType) and the message (like the
> > argument for doesNotUnderstand:) that represents the FFI call.
> >
>
> I don't like the idea of adding a plugin-specific mechanism like this to
> the VM. I know it's not as convenient, but maybe something similar can be
> achieved with error codes in fallback code? There already is BAD_ARGUMENT,
> maybe there's a way to encode which argument is bad in the error code?
>
> Fabio
>
>
> > The pair of (argObject, argType) could be expressed as FFICallArgument:
> >
> > FFICallArgument
> > argObject ...