Seite 1 von 1

libffi

Verfasst: Mo Dez 10, 2012 11:29 am
von Xin
Moin zusammen,

Hat sich jemand bereits mit der libffi auseinandergesetzt?

Unter Windows habe ich sie bisher noch nicht ans Laufen bekommen, unter Linux bekomme ich das Beispielprogramm nichtmals freiwillig durch den Compiler. Nach einer kleiner Anpassung sieht das Beispielprogramm so aus:

Code: Alles auswählen

#include <stdio.h>
#include <ffi.h>

int main()
{
  ffi_cif cif;
  ffi_type *args[1];
  void *values[1];
  char const *s;
  int rc;
  
  typedef void (*func)( void );                       // hinzugefügt
  
  /* Initialize the argument info vectors */    
  args[0]   = &ffi_type_pointer;
  values[0] = &s;
  
  func funcptr = reinterpret_cast< func >( puts );          //hinzugefügt
  
  /* Initialize the cif */
  if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
                   &ffi_type_uint, args) == FFI_OK)
    {
      s = "Hello World!";
      ffi_call(&cif, funcptr, &rc, values);                 // puts nach funcptr getauscht
      /* rc now holds the result of the call to puts */
      
      printf( "rc: %d\n", rc );
      
      /* values holds a pointer to the function's arg, so to 
         call puts() again all we need to do is change the 
         value of s */
//      s = "This is cool!";
      ffi_call(&cif, funcptr, &rc, values);                 // puts  nach funcptr getauscht
      printf( "rc: %d\n", rc );
    }
  
  return 0;
}
und ich erhalte folgendes:

Code: Alles auswählen

xin@trinity:~/xsd/try/ffi_ubuntu$ valgrind ./a.out 
==6316== Memcheck, a memory error detector
==6316== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==6316== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==6316== Command: ./a.out
==6316== 
Hello World!
rc: 13
==6316== Invalid read of size 8
==6316==    at 0x4E374A2: ffi_call (in /usr/lib/x86_64-linux-gnu/libffi.so.6.0.0)
==6316==    by 0x4009A2: main (in /home/xin/xsd/try/ffi_ubuntu/a.out)
==6316==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==6316== 
...
Mit anschließendem Segmentation Fault.

Der erste Aufruf funktioniert, der zweite hingegen fliegt mir um die Ohren.

Code: Alles auswählen

xin@trinity:~/xsd/try/ffi_ubuntu$ uname -a
Linux trinity 3.5.0-17-generic #28-Ubuntu SMP Tue Oct 9 19:31:23 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux

Re: libffi

Verfasst: Mo Dez 10, 2012 1:57 pm
von Xin

Code: Alles auswählen

 int rc;
ist der Übeltäter.

An dem Code musste ich ja bereits einiges ändern, damit er durch meinen Compiler rennt. Auf einem 32-Bit-System läuft der Code auch... wenn auch nicht bei mir, denn wie im anderen Thread beschrieben, bekomme ich die 32-Bit Version nicht zusammenkompiliert. (Ein erfolgreicher Tag also...)

Puts scheint auf 64-Bit Systemen ein 64 Bit Interger zurück zu geben - kann das mal einer Bestätigen!? Es wäre ja logisch, aber bisher habe ich noch keine Bestätigung dazu bekommen. Die Variable rc ist aber int (32 Bit).
Um das kompatibel zu halten nehme man den Datentyp ffi_arg:

Code: Alles auswählen

#include <stdio.h>
#include <ffi.h>

void show( ffi_cif const & cif )
{
    printf( "abi %x\n", cif.abi);
    printf( "nargs %x\n", cif.nargs);
    printf( "bytes %x\n", cif.bytes);
    printf( "flags %x\n", cif.flags);
#ifdef FFI_EXTRA_CIF_FIELDS
    printf( "extra fields\n");
#endif
}


int main()
{
  ffi_cif cif;
  ffi_type *args[1];
  void *values[1];
  char const *s;
  ffi_arg rc;
  
  typedef void (*func)( void );
  
  /* Initialize the argument info vectors */    
  args[0]   = &ffi_type_pointer;
  values[0] = &s;
  
  func funcptr = reinterpret_cast< func >( puts );
  /*
typedef struct {
  ffi_abi abi;
  unsigned nargs;
  ffi_type **arg_types;
  ffi_type *rtype;
  unsigned bytes;
  unsigned flags;
#ifdef FFI_EXTRA_CIF_FIELDS
  FFI_EXTRA_CIF_FIELDS;
#endif
} ffi_cif;
*/
  /* Initialize the cif */
  if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
                   &ffi_type_uint, args) == FFI_OK)
    {
      s = "Hello World!";
      ffi_call(&cif, funcptr, &rc, values);
      /* rc now holds the result of the call to puts */
      
      printf( "rc: %d\n", rc );
      
      /* values holds a pointer to the function's arg, so to 
         call puts() again all we need to do is change the 
         value of s */
    printf( "2.\n" );
      s = "This is cool!";

      ffi_call(&cif, funcptr, &rc, values);
      printf( "rc: %d\n", rc );
    }
  
  return 0;
}

Re: libffi

Verfasst: Do Dez 13, 2012 9:43 am
von Orioner
Ich kann das nicht bestätigen, aber was ich sagen kann, ist, dass eine Integervariable auf einem 64-Bit-System 64 Bit und nicht 32 Bit hat. Hilft das?

Re: libffi

Verfasst: Do Dez 13, 2012 7:03 pm
von Xin
Orioner hat geschrieben:Ich kann das nicht bestätigen, aber was ich sagen kann, ist, dass eine Integervariable auf einem 64-Bit-System 64 Bit und nicht 32 Bit hat. Hilft das?
Es gibt die Vermutung, dass was auch immer als Ergebnis zurückkommt auf ein 64-Bit int gecastet wird, dass dann an die Ergebnisvariable geschrieben wird.

Ansonsten ist "int" "mindestens" 32 Bit - und üblicherweise auch auf 64 Bittern auch nur 32 Bit groß. Für ein 64 Bit-int sollte man eher long int.anfordern.