newlisp/util/ffitest.c

231 lines
3.9 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
/*
testffi.c
test FFI correct passing of parameter and return types
this file is used in qa-specific-tests/qa-libffi
compile using either:
gcc -m32 ffitest.c -shared -o ffitest.dylib
or
gcc -m64 ffitest.c -shared -o ffitest.dylib
all intx tupes must correctly handle sign-extension
and unsigning
e.g.: (ret_uint8 -1) => 255
(ret_int8 255) => -1
user API type ffi type
------------- --------
"byte" &ffi_type_uint8
"char" &ffi_type_sint8
"short int" &ffi_type_sint16
"unsigned short int" &ffi_type_uint16
"unsigned int" &ffi_type_uint32
"int" &ffi_type_sint32
#ifdef NEWLISP64
"long" &ffi_type_sint64
#else
"long" &ffi_type_sint32
#endif
"long long" &ffi_type_sint64
"float" &ffi_type_float
"double" &ffi_type_double
"char*" &ffi_type_pointer input string or address, return string
"void*" &ffi_type_pointer input string or address, return address
#endif
*/
char ret_sint8(char number)
{
return(number);
}
char ret_uint8(unsigned char number)
{
return(number);
}
short int ret_sint16(int number)
{
return(number);
}
short int ret_uint16(unsigned int number)
{
return(number);
}
int ret_sint32(int number)
{
return(number);
}
int ret_sint32_void(void)
{
return(-1);
}
unsigned int ret_uint32(unsigned int number)
{
return(number);
}
long long ret_sint64(long long number)
{
return(number);
}
float ret_float(float number)
{
return(number);
}
double ret_double(double number)
{
return(number);
}
double add_double(double number1, double number2)
{
return(number1 + number2);
}
char * ret_pointer(char * ptr)
{
char * upper;
upper = ptr;
while(*ptr) { *ptr = toupper(*ptr); ptr++; }
return(upper);
}
char * string_copy(char * from, char * to)
{
strcpy(to, from);
return(to);
}
/* test ffi closure API */
void (*function)(char * str, int inum, double fnum);
void register_callback(void * ptr)
{
function = ptr;
}
void trigger_callback()
{
double dnum = 12345.67890;
(*function)(">>>>> callback API ", 1234567890, dnum);
}
/* test simple ffi */
void (*function_simple)(char * str, int inum);
void register_callback_simple(void * ptr)
{
function_simple = ptr;
}
void trigger_callback_simple() /* only handles strings and integers */
{
long inum = 1234567890;
(*function_simple)(">>>>> callback API ", inum);
}
/* test struct API */
typedef struct clock
{
char hour;
int min;
short int sec;
} clock;
clock addClock(clock in)
{
in.hour += 1;
in.min += 1;
in.sec += 1;
return in;
}
typedef struct foo
{
char first;
int second;
short int third;
char * word;
} foo;
foo * useFoo(int value)
{
foo * bar = malloc(sizeof(foo));
bar->first = 1 + value;
bar->second = 2 + value;
bar->third = 3 + value;
bar->word = "hello world";
return bar;
}
/* miscellanous tests */
typedef struct
{
double dat[2];
} gsl_complex;
/* structure return
(struct 'complex "double" "double")
(import LIB "gsl_complex_rect" "complex" "double" "double")
(gsl_complex_rect 3.0 4.0) ;=> (3 4)
*/
gsl_complex complex_test(gsl_complex gs)
{
return(gs);
}
/* mixed floats intd for simple ffi and 32bit
(import "ffitest.dylib" "mixed_int_float")
(get-string (mixed_int_float 123 (flt 123.456) 456 (flt 789.123)))
;=> "123 123.456001 456 789.122986\n"
*/
char * mixed_int_float(int x, float a, int y, float b)
{
static char buff[100];
sprintf(buff, "%d %f %d %f\n", x, a, y, b);
return(buff);
}
/* arrays */
int array_test(int n, int m, double * ptr[])
{
int i , j;
for(i = 0; i < n; i++)
for(j = 0; j < m; j++)
printf("%lf ", ptr[i][j]);
return(0);
}
/* eof */