From: Martin Uecker <ma.uecker@gmail.com>
To: "Kaz Kylheku (libffi)" <382-725-6798@kylheku.com>
Cc: Florian Weimer <fweimer@redhat.com>,
Martin Uecker via Libffi-discuss <libffi-discuss@sourceware.org>,
Libffi-discuss
<libffi-discuss-bounces+382-725-6798=kylheku.com@sourceware.org>
Subject: Re: wide function pointer type
Date: Wed, 20 Oct 2021 20:52:23 +0200 [thread overview]
Message-ID: <dc1111e49609330f82a7b9061ec29d0989372565.camel@gmail.com> (raw)
In-Reply-To: <bfbd97ae6e2466cf12b1760206a69f6e@mail.kylheku.com>
Am Mittwoch, den 20.10.2021, 01:24 -0700 schrieb Kaz Kylheku (libffi):
> 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);
> >
> > 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.
The difference here is that something which is a fundamental
type in most other languages is split up into two things
in C.
> 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.
Generators for language wrappers do
not read documentation ;-)
> A declarative mechanism which indicates that a given
> context parameter goes with a given function could
> exist instead of _Wide.
Yes, I had considered this too.
> Such a thing was introduced 22 years ago for VLA's:
>
> void fun(int m, double a[m]);
Sure, but VLA types are also underdeveloped
The limitations are:
- You can not store a pointer to a VLA in the struct.
- You can not put the size later.
- You can not
always automatically verify that
the size is correct at the caller side because
the semantic type of a
declaration is:
void fun(int m, double a[*]);
All this would be avoided with a wide
pointer type that integrates the size into the
pointer (as in FORTRAN). This was in fact proposed
by Dennis Ritchie himself a long time ago:
Ritchie DM. Variable-size arrays in C.
The Journal of C Language Translation 1990;2:81-86.
> 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.
No it does not assume this. You can always keep
doing this as before.
> 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.
I am not sure what you are talking about..
> 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
> }
Not at all. C++ has std::function for this purpose
which is usually even bigger than two words because
it does an optimization for small objects.
> 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.
I never claimed that "all callbacks use void*". So please
do not use strawman arguments.
> > 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?
If _Wide is a qualifier as in the proposal
Function types nothing changes.
Martin
next prev parent reply other threads:[~2021-10-20 18:52 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-10-10 11:32 Martin Uecker
2021-10-17 23:35 ` Anthony Green
2021-10-18 5:33 ` Martin Uecker
2021-10-18 5:58 ` Martin Uecker
2021-10-18 7:36 ` Florian Weimer
2021-10-18 7:56 ` Martin Uecker
2021-10-19 9:22 ` Florian Weimer
2021-10-19 9:43 ` Martin Uecker
2021-10-19 10:15 ` Florian Weimer
2021-10-19 12:13 ` Martin Uecker
2021-10-20 8:24 ` Kaz Kylheku (libffi)
2021-10-20 18:52 ` Martin Uecker [this message]
2021-10-20 9:10 ` Florian Weimer
2021-10-20 9:21 ` Martin Uecker
2021-10-20 9:27 ` Florian Weimer
2021-10-20 17:27 ` Kaz Kylheku (libffi)
2021-10-21 9:48 ` Florian Weimer
2021-10-10 17:01 Kaz Kylheku (libffi)
2021-10-10 17:44 ` Martin Uecker
2021-10-10 17:49 ` Daniel Colascione
2021-10-10 18:05 ` Martin Uecker
2021-10-10 18:17 ` Daniel Colascione
2021-10-10 18:47 ` Martin Uecker
2021-10-10 18:57 ` Daniel Colascione
2021-10-10 19:24 ` Martin Uecker
2021-10-16 8:08 ` Jarkko Hietaniemi
2021-10-16 9:35 ` Jarkko Hietaniemi
2021-10-10 18:31 ` Kaz Kylheku (libffi)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=dc1111e49609330f82a7b9061ec29d0989372565.camel@gmail.com \
--to=ma.uecker@gmail.com \
--cc=382-725-6798@kylheku.com \
--cc=fweimer@redhat.com \
--cc=libffi-discuss-bounces+382-725-6798=kylheku.com@sourceware.org \
--cc=libffi-discuss@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).