From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <382-725-6798@kylheku.com> Received: from smtp-out-so.shaw.ca (smtp-out-so.shaw.ca [64.59.136.137]) by sourceware.org (Postfix) with ESMTPS id 8764D384802F for ; Fri, 19 Mar 2021 02:36:44 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 8764D384802F Received: from kylheku.com ([70.79.163.252]) by shaw.ca with ESMTPA id N50CltQDMHmS3N50ElFcoQ; Thu, 18 Mar 2021 20:36:43 -0600 X-Authority-Analysis: v=2.4 cv=MaypB7zf c=1 sm=1 tr=0 ts=60540e3b a=95A0EdhkF1LMGt25d7h1IQ==:117 a=95A0EdhkF1LMGt25d7h1IQ==:17 a=IkcTkHD0fZMA:10 a=SMorJkV_YP8A:10 a=dESyimp9J3IA:10 a=5KLPUuaC_9wA:10 a=CZWN7zbASATn-x4hIAcA:9 a=QEXdDO2ut3YA:10 Received: from www-data by kylheku.com with local (Exim 4.72) (envelope-from <382-725-6798@kylheku.com>) id 1lN50C-0007Gv-Pu; Thu, 18 Mar 2021 19:36:40 -0700 To: ShaJunxing Subject: Re: How to call 'printf' using =?UTF-8?Q?libffi=3F?= 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: Thu, 18 Mar 2021 19:36:40 -0700 From: "Kaz Kylheku (libffi)" <382-725-6798@kylheku.com> Cc: Anthony Green , libffi-discuss In-Reply-To: <0b7f2827-e209-2c58-7118-9fec4770ae1c@163.com> References: <00aed94e-6f76-f6d7-9878-a3eb50dce543@163.com> <0b7f2827-e209-2c58-7118-9fec4770ae1c@163.com> Message-ID: <8b91422069c635427e0e3f57c1814f47@mail.kylheku.com> X-Sender: 382-725-6798@kylheku.com User-Agent: Roundcube Webmail/0.9.2 X-CMAE-Envelope: MS4xfJXCo8o/UXI891xRt8YxE3iHMGbElPt7HtEIu7fQQR1uvnH0K8Sg9BAFSvv95HHDgoYC3zlwfWEjmMmmpgc+DLwSUdJaCLh30jtgmTqTY2ldSXrfH6Il Chk854QMqDsYJZIRK/NRlznura/deZr2vrsqdpDtlZY4KNG526LbrkEgamRl/DL4Df0YbcHmpgpVVSfhbNyfXRdjTrGBjJ6EwOPeFcrOHNe/moF1NciFKxme x3pNdiaUPD84s6PrxXGUE9EzpyV2PgRAVG7Uy5Lou9A= X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00, FROM_STARTS_WITH_NUMS, KAM_DMARC_STATUS, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) 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: Fri, 19 Mar 2021 02:36:46 -0000 On 2021-03-18 19:08, ShaJunxing via Libffi-discuss wrote: > Yesterday after sending email I also realized maybe different > parameters needs different cif, and I did some experiments, it exactly > works. But I got two more problems. The first is, I found > ffi_prep_cif() works fine in this situation, so what is > ffi_prep_cif_var() different from? Note that what you are saying is exactly analogous to this: "When I declare printf like this: extern int printf(const char *fmt, char *arg); everything works; I can call it as printf("Hello, %s!\n", name); and I get the expected output. why do I have to have a correct variadic prototype by including ? It might look like it's working, but it's undefined behavior; it is not required to work and could prove to be nonportable. Variadic functions do not necessarily pass arguments the same way as ordinary functions. In order for libffi to build the correct parameter passing mechanism for the descriptor, it needs to be informed that the target function is variadic. Then, depending on the target architecture, the libffi code might do some things differently for calling that function. Those different things might depend on how many arguments there are and what types. > The second is, I found printf() > cannot properly handle float type in my machine, my code is: Note that when argument expressions of float type are passed as the trailing arguments of a variadic function, they are promoted to type double. That's a C language rule. The rule also applies to old style functions with undeclared parameter lists,e .g. int old_style(); float f =3D 3.14; old_style(f); /* promoted to double! */ /* definition must be this */ int old_style(arg) double arg; { } The %f conversion specifier in printf does not mean "float". It means "fixed digit format". There are two other formats: %e, exponential and %g, general (which chooses exponential or fixed digit). All of these take an argument of type double. >=20 > #include > #include > intmain() { > ffi_cif cif; > ffi_type *atypes[2] =3D {&ffi_type_pointer, &ffi_type_float}; > if(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_sint, atypes) =3D=3D= =20 > FFI_OK) { > char*s =3D "hello %f\n"; > floatf =3D 3.14; > void*avalues[2] =3D {&s, &f}; > ffi_arg rvalue; > ffi_call(&cif, (void*)printf, &rvalue, avalues); > } > return0; > } >=20 > It always outputs zero (maybe other unexpected result). I changed the > second argument to double, char *, int, long ... all correct, except > float. Not only must the FFI type be ffi_type_double, but you must make sure that the object which the corresponding argument points to is of type double. FFI doesn't perform any conversion; it has no idea: there is just a void * pointing at an argument object which is expected to match the exact type that the type descriptor states.