From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6456 invoked by alias); 4 Dec 2013 18:28:46 -0000 Mailing-List: contact libffi-discuss-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libffi-discuss-owner@sourceware.org Received: (qmail 6444 invoked by uid 89); 4 Dec 2013 18:28:45 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=1.3 required=5.0 tests=AWL,BAYES_50,RDNS_NONE autolearn=no version=3.3.2 X-HELO: exprod5og107.obsmtp.com Received: from Unknown (HELO exprod5og107.obsmtp.com) (64.18.0.184) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) SMTP; Wed, 04 Dec 2013 18:28:44 +0000 Received: from cinmlip12.e2k.ad.ge.com ([12.71.149.1]) (using TLSv1) by exprod5ob107.postini.com ([64.18.4.12]) with SMTP ID DSNKUp90VIMxEQfdvjqGIdpAc9sAfwAJJ1ne@postini.com; Wed, 04 Dec 2013 10:28:44 PST Received: from unknown (HELO ALPMBHT02.e2k.ad.ge.com) ([3.159.19.195]) by cinmlip12.e2k.ad.ge.com with ESMTP/TLS/AES128-SHA; 04 Dec 2013 13:28:36 -0500 Received: from ALPMBCND02.e2k.ad.ge.com (3.159.19.11) by ALPMBHT02.e2k.ad.ge.com (3.159.19.195) with Microsoft SMTP Server (TLS) id 14.3.146.0; Wed, 4 Dec 2013 13:28:35 -0500 Received: from ALPMBAPA05.e2k.ad.ge.com ([169.254.5.229]) by ALPMBCND02.e2k.ad.ge.com ([169.254.8.138]) with mapi id 14.03.0146.000; Wed, 4 Dec 2013 13:28:35 -0500 From: "Hogan, D. (GE Power & Water)" To: Andrew Haley CC: Alan Modra , Jakub Jelinek , "libffi-discuss@sourceware.org" Subject: RE: RFC: variadic closures in x86/x86_64 Date: Wed, 04 Dec 2013 18:28:00 -0000 Message-ID: References: <52931854.6080007@redhat.com> <20131125093715.GU892@tucnak.redhat.com> <5293221D.4010505@redhat.com> <20131126142723.GD9211@bubble.grove.modra.org> <529F1E3E.4010401@redhat.com> In-Reply-To: <529F1E3E.4010401@redhat.com> Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-IsSubscribed: yes X-SW-Source: 2013/txt/msg00234.txt.bz2 On Wed, Dec 04, 2013 at 00:07:21AM, Andrew Haley wrote: > Please, I'm finding this extremely difficult to understand. Where is > the variadic function? You say that a C shared library "executes" a > callback, but what does that mean? Sorry about the confusion. I mean the driver sends to the shared library a struct of function pointers when it creates a model instance. It is represented in JNA as a Structure of Callbacks. One of the function pointers is variadic: typedef struct {=20 void (*logger)(fmiComponent c, fmiString instanceName, fmiStatus status, fmiString category, fmiString message, ...);=20 void *(*allocateMemory)(size_t nobj, size_t size);=20 void (*freeMemory) (void *obj);=20 } fmiCallbackFunctions; And this is a function inside of every shared library model: fmiComponent instantiateModel(char* fname, fmiString instanceName, fmiString GUID, fmiCallbackFunctions functions, fmiBoolean loggingOn) The model dereferences the function pointers inside of a common file, fmuTemplate.c, which is included in every model. Here's an example: fmiStatus fmiSetInteger(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiInteger value[]){ int i; ModelInstance* comp =3D (ModelInstance *)c; ... if (comp->loggingOn) comp->functions.logger(c, comp->instanceName, fmiOK, "log", "fmiSetInteger: nvr =3D %d",nvr); ... } > Right, so a C program thinks it's calling C, but in fact it's calling > Java, and a libffi closure provides the glue. Yeah. JNA uses a libffi closure to provide the glue. The problem is closures cannot currently access variadic arguments. If you try to write an implementation of the logger above as a Callback in JNA, it won't be able to access anything beyond message. This is a limitation inherited from libffi's closure. > Ah! OK, so the function that is called as a C function is a libffi > closure, and it is called in a variadic form. Right. > Again, I don't know what it means to "run a variadic callback." Does > this mean that the shared library contains this callback function, or > that it calls it? The shared library dereferences a pointer to a variadic function. > Why do you not define a variadic C function which does this: > > void f1(int n, ...) { > va_list ap; In the libffi manual, there's a TODO about variadic closures. My interpretation of variadic closures is a closure which can access variadic arguments without sending in the number of arguments and types at the ffi_prep_cif or ffi_prep_cif_var time. Once you have a variadic closure, you should be call it any number of times with any number of variadic arguments. If libffi had that, JNA could create a closure and the Java callback/function pointer could access variadic arguments in any manner that it sees fit. It wouldn't need an application specific C wrapper that captures the varargs. For instance, taking the simple testsuite/libffi.call/cls_sint.c, what would it look like if you had variadic closures? Below is similar to what it would look like with this patch. diff --git a/testsuite/libffi.call/cls_sint.c b/testsuite/libffi.call/cls_s= int.c index c7e13b7..d456be5 100644 --- a/testsuite/libffi.call/cls_sint.c +++ b/testsuite/libffi.call/cls_sint.c @@ -7,14 +7,21 @@ /* { dg-do run } */ #include "ffitest.h" =20 -static void cls_ret_sint_fn(ffi_cif* cif __UNUSED__, void* resp, void** ar= gs, +static void cls_ret_sint_fn(ffi_cif* cif, void* resp, void** args, void* userdata __UNUSED__) { + void *vals[1]; + *(ffi_arg*)resp =3D *(signed int *)args[0]; - printf("%d: %d\n",*(signed int *)args[0], - (int)*(ffi_arg *)(resp)); + + /* Assuming the first variadic argument is sint. */ + CHECK(ffi_closure_va_arg(cif, &ffi_type_sint32, &vals[0]) =3D=3D FFI_OK); + + printf("%d: %d %d\n",*(signed int *)args[0], + (int)*(ffi_arg *)(resp), *(signed int *)vals[0]); + } -typedef signed int (*cls_ret_sint)(signed int); +typedef signed int (*cls_ret_sint)(signed int, ...); =20 int main (void) { @@ -33,8 +40,10 @@ int main (void) =20 CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_sint_fn, NULL, code) =3D= =3D FFI_OK); =20 - res =3D (*((cls_ret_sint)code))(65534); - /* { dg-output "65534: 65534" } */ + res =3D (*((cls_ret_sint)code))(65534, 32); + /* { dg-output "65534: 65534 32" } */ + res =3D (*((cls_ret_sint)code))(65534, 32, 64.5); /* 64.5 is ignored but= allowed */ + /* { dg-output "65534: 65534 32" } */ printf("res: %d\n",res); /* { dg-output "\nres: 65534" } */