It's very important to name the types explicitely in order to avoid confusion

See https://lists.pharo.org/pipermail/pharo-dev_lists.pharo.org/2017-November/268059.html

Le��ven. 22 mai 2020 ����15:30, Esteban Lorenzano <estebanlm@netc.eu> a ��crit��:


On 22 May 2020, at 15:25, Esteban Lorenzano <estebanlm@netc.eu> wrote:


On 22 May 2020, at 15:07, Ben Coman <btc@openinworld.com> wrote:



On Fri, 22 May 2020 at 15:25, Esteban Lorenzano <estebanlm@netc.eu> wrote:
On 22 May 2020, at 04:24, Sean P. DeNigris <sean@clipperadams.com> wrote:

Esteban Lorenzano wrote
The class comments are not clear?

Maybe it's me ;-)

No. I struggled with this also, and still don't have it fully grasped.�� I could follow Eteban's��advice in a particular case I asked about, but still feel hard to reason about next time.��
��


Esteban Lorenzano wrote
Opaque object =��https://en.wikipedia.org/wiki/Opaque_data_type
&lt;https://en.wikipedia.org/wiki/Opaque_data_type&gt;
External object = a pointer to something.��

For example, why is ObjCClass a subclass of FFIExternalObject instead of
FFIOpaqueObject when the docs say that a "Class [is] An opaque type that
represents an Objective-C class"? Also, is the distinction just conceptual?
I don't see what either class "buys" you in behavior since they are siblings
that both pretty much have no methods.��

This is because ObjCClass = SomeOpaqueStructurePointer (is already a pointer), same as ObjCSelector and ObjCMethod.
Difference is subtle, because is just a different way of representing the same.��

The easiest way I have to explain is:��

As a prelude to my next comment, how does "External" distinguish between the two case?
Aren't both cases dealing with external C data?��

You use an OpaqueObject when you will refer to "the opaque type" in calls as: ��someFunction(opaqueobject *someArg).
You use an ExternalObject when you will refer to "the opaque type" in calls as: someFunction(externalobject someArg).

That makes the distinction really clear.�� So if now IIUC, both cases deal with "opaque types"��
with the *only* difference between the two being the arity?
Then I propose the following��naming would be more intention revealing...

OpaqueObject when you will refer to "the opaque type" in calls as: ��someFunction(opaqueobject *someArg).
OpaquePointer when you will refer to "the opaque type" in calls as: someFunction(opaquepointer someArg).����


And to test my new understanding, the matching typdefs and FFI calls would be...

OPAQUE OBJECT
-�� typedef MyOpaqueType��opaqueobject.
-�� int someFunction(opaqueobject *someArg)��

-�� FFIOpaqueObject subclass: #MyOpaqueType.
-�� self ffiCall: #(int someFunction( MyOpaqueType *ot ) ).
- opaque type has arity 0, so FFI needs to take a pointer to it����
��
OPAQUE POINTER
-�� typedef MyOpaqueObject *opaquepointer.
-�� int someFunction(opaquepointer someArg)��

-�� FFIOpaquePointer subclass: # MyOpaqueType.
-�� self ffiCall: #(int someFunction( MyOpaqueType ot ) ).
- opaque type has arity of 1,�� so FFI��uses it directly�� �� ��

The latter FFI call is without the *��� because FFIOpaquePointer is already a pointer.��
In practice, both FFI calls are identical, and you use the one that matches the C header definitions.


...or maybe I still don't get it.

No, you got it :)
Part of the confusion is the horribly bad name that FFIExternalObject has :/
Other part is my inability to explain it ;)

But yes, this is all as you say.
If someone wants to do a PR changing the names and maybe enhancing my comments��� it would be nice :D
Of course keeping the old names as deprecated! ;)


Esteban


��cheers -ben