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

static __thread  ffi_type *arg_types[200];
static __thread  void *arg_values[200];

unsigned char
foo2(unsigned int x, float y, int z)
{
    unsigned char result = x - y - z;
    return result;
}

unsigned char
foo1(unsigned int x, float y)
{
    unsigned char result = x - y;
    return result;
}

static void*
thread2 (void *param)
{
    ffi_cif cif;
    ffi_status status;
    ffi_arg result;

    arg_types[0] = &ffi_type_uint;
    arg_types[1] = &ffi_type_float;
    arg_types[2] = &ffi_type_uint;

    status = ffi_prep_cif(&cif, FFI_DEFAULT_ABI,
        3, &ffi_type_uint8, arg_types);

    unsigned int arg1 = 42;
    float arg2 = 5.1;
    int arg3 = 1;

    arg_values[0] = &arg1;
    arg_values[1] = &arg2;
    arg_values[2] = &arg3;

    ffi_call(&cif, FFI_FN(foo2), &result, arg_values);

    if (result != 35)
       printf("result thread2 is %hhu\n", (unsigned char)result);

    pthread_exit(NULL);
}

static void*
thread1 (void *param)
{
    ffi_cif cif;
    ffi_status status;
    ffi_arg result;

    arg_types[0] = &ffi_type_uint;
    arg_types[1] = &ffi_type_float;

    status = ffi_prep_cif(&cif, FFI_DEFAULT_ABI,
        2, &ffi_type_uint8, arg_types);

    unsigned int arg1 = 42;
    float arg2 = 5.1;

    arg_values[0] = &arg1;
    arg_values[1] = &arg2;

    ffi_call(&cif, FFI_FN(foo1), &result, arg_values);

    if (result != 36)
       printf("result thread1 is %hhu\n", (unsigned char)result);

    pthread_exit(NULL);
}




int
main(int argc, const char **argv)
{
  pthread_t thread[100];
  int i = 0;

   for (i = 0; i< 100; i++) {
	   pthread_create(&thread[i],
		0, i%2?thread1:thread2, 0);
   }

   sleep (3);

}

