From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from omta001.cacentral1.a.cloudfilter.net (omta001.cacentral1.a.cloudfilter.net [3.97.99.32]) by sourceware.org (Postfix) with ESMTPS id DF7D53858C3A; Wed, 20 Oct 2021 08:24:41 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org DF7D53858C3A Received: from shw-obgw-4004a.ext.cloudfilter.net ([10.228.9.227]) by cmsmtp with ESMTP id d09VmAcqnczbLd6ttmu9ci; Wed, 20 Oct 2021 08:24:41 +0000 Received: from kylheku.com ([70.79.163.252]) by cmsmtp with ESMTPA id d6trmMmw2a8XRd6trmsv7Z; Wed, 20 Oct 2021 08:24:41 +0000 X-Authority-Analysis: v=2.4 cv=Ov8sdwzt c=1 sm=1 tr=0 ts=616fd249 a=95A0EdhkF1LMGt25d7h1IQ==:117 a=95A0EdhkF1LMGt25d7h1IQ==:17 a=IkcTkHD0fZMA:10 a=SMorJkV_YP8A:10 a=8gfv0ekSlNoA:10 a=2YRIkpWXIrqkEbuXA-kA:9 a=QEXdDO2ut3YA:10 Received: from www-data by kylheku.com with local (Exim 4.72) (envelope-from <382-725-6798@kylheku.com>) id 1md6tq-0002y7-B8; Wed, 20 Oct 2021 01:24:38 -0700 To: Martin Uecker Subject: Re: wide function pointer type X-PHP-Originating-Script: 501:rcmail.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: quoted-printable Date: Wed, 20 Oct 2021 01:24:38 -0700 From: "Kaz Kylheku (libffi)" <382-725-6798@kylheku.com> Cc: Florian Weimer , Martin Uecker via Libffi-discuss , Libffi-discuss In-Reply-To: References: <9362563f8803f575d00c03835d2897b3836a7645.camel@gmail.com> <857da973fe5bbb94a363114262b57d42b35cc1f6.camel@gmail.com> <87czo2hjiq.fsf@oldenburg.str.redhat.com> <8d2ddbb76479ce3ad7f99acb3f0b79a6a8d1440b.camel@gmail.com> <87bl3lgyha.fsf@oldenburg.str.redhat.com> <6a0299e6b3c47cddd88b24d569fca8aeb4717aeb.camel@gmail.com> <87o87lfhi3.fsf@oldenburg.str.redhat.com> Message-ID: X-Sender: 382-725-6798@kylheku.com User-Agent: Roundcube Webmail/0.9.2 X-CMAE-Envelope: MS4xfKfXik60R1tiPh4MgKRBrmhzxo055peObkJCCaL8EHMbLhKR0YWZYKLxvow6bAwDF8BwA8dHo+P90+baIprxscfABquOMr+Igb9fBYiXnhEhfZVKxZOv Z6ltI0olz6gdcUAp+VDR+ItVkoEH/guBXK65gAmKVMsPGuO9dMrRztbSyL92CJet6I2apuhLliNAGDGm9ChMUSj30ia6183J7e6SpeORgzowV3noXexIykdx sbDGFqwvIqBF+qbIoIbwaLmkAAJ5Fr612JlvQn59fgohH6Of8jHtvNqZfg3v7dDawSSgBa1+GQY9vdhsdX0qiOEj51wSjB2VggK28dQZWc0= X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, FROM_STARTS_WITH_NUMS, HEADER_FROM_DIFFERENT_DOMAINS, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=no autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libffi-discuss@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libffi-discuss mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 20 Oct 2021 08:24:43 -0000 On 2021-10-19 05:13, Martin Uecker via Libffi-discuss wrote: > void foo( > void (cb1)(void* data, int a), void* data1, > void* other_data); >=20 > Here a human (and maybe also a machine) could guess > that data1 belongs to cb1 but not other_data. But > it is not clear and in more complicated cases > even less so. That's a property of almost every C API. You cannot guess the properties from the declaration alone. If memcpy didn't have the const on the source argument, you couldn't guess which argument is the destination and which is the source. y Argument names and analogy to x tell you which argument of pow is the base and which the exponent. That's the job of documentation. A declarative mechanism which indicates that a given context parameter goes with a given function could exist instead of _Wide. Such a thing was introduced 22 years ago for VLA's: void fun(int m, double a[m]); An obvious convention is possible, and often occurs in practice: namely, the context parameter in the API function is given a name which exactly matches the one in the function pointer: void foo(void (cb1)(void *the_context, int a), void *unrelated_data, void *the_context); Your proposal also assumes that closures must always be specified as two argument words, which is an inappropriate choice to foist onto programmers. So that is to say, you're taking it for granted that you want to keep a distinct disadvantage of the current approach and just wrap it in some syntactic sugar machinery so that the two arguments appear encapsulated as some _Wide thing passed by value. But callback interfaces can easily use just a single argument word to point to a object that is passed with reference semantics; that object has a function and context data. In high level languages with closures, like Lisp dialects, closures are of the same "size" as other values; e.g. 32 or 64 bit pointer-sized word or what have you. C++ callback objects are usually one pointer also. void f(CallBackBase *cb) { (*cb)(42); // via operator () // or cb->callBack(42); // regular member function } C programs do this too: void f(struct obj *o) { o->ops->callback(o, 42); } Or with the ops table in the object instance: void f(struct obj *o) { o->ops.callback(o, 42); } The idea that all callback interfaces in C use a function and a void * argument is a false; you have to survey the entire field of practice in this general area. > void foo(void (_Wide cb1)(int a), void* other_data); Without _Wide, we have void (cb1)(int a) That (cb1)(int a) is a function declarator (with superfluous parentheses); but when that occurs as a parameter, it declares a function pointer: it is equivalent to: void (*cb1)(int a) But it looks like void (_Wide cb1)(int) might not be similarly equivalent to void (_Wide *cb1)(int) and the difference could be useful. Furthermore, given that you can have a _Wide value W, or a pointer to a _Wide value PW, do you call them using different syntax? Is it just W(arg, ...) and PW(arg, ....)? Or do we require (*PW)(arg, ...)? If we don't require it, is it because of a decay rule, so that we can write PW(arg, ...) or (*PW)(arg, ...) or (**PW)(arg, ...)? and same with W? Or is it due to separately articulated semantics: that the function call operator works with a _Wide and a pointer-to_Wide, without any "decay" conversion going on?