Skip to content

Instantly share code, notes, and snippets.

@jjpe
Last active August 29, 2015 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jjpe/96f33585d8986fceb0e5 to your computer and use it in GitHub Desktop.
Save jjpe/96f33585d8986fceb0e5 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <vector>
#include <limits>
#include "stdint.h"
#include <cstring>
#include <sys/time.h>
#include <ffi.h>
#include <dlfcn.h>
#include <cstdio>
extern int gettimeofday(struct timeval *tv, struct timezone *tz);
void waitFor (unsigned int secs) {
std::cout << "Sleeping for " << secs
<< ((secs == 1) ? " second" : " seconds")
<< std::endl;
int retTime = time(0) + secs; // Get finishing time.
while (time(0) < retTime); // Loop until it arrives.
}
const int wait_time = 1;
int main() {
std::cout << "Test started..." << std::endl;
// Get a handle to the dynamic lib
const char *dynlib_name = "";
void *dynlib_handle;
if (dynlib_name == NULL || strlen(dynlib_name) == 0) {
// Default to a handle for the main program
dynlib_handle = ::dlopen(NULL, RTLD_LAZY);
std::cout << "Got main program handle" << std::endl;
} else {
dynlib_handle = ::dlopen(dynlib_name, RTLD_LAZY);
std::cout << "Got handle to dynamic library \""
<< dynlib_name << "\"" << std::endl;
}
// Regular fn call
struct timeval tv;
std::cout << "pre-alloc: tv.tv_sec = "
<< tv.tv_sec << std::endl;
waitFor(wait_time);
gettimeofday(&tv, NULL);
std::cout << "post-alloc: tv.tv_sec = "
<< tv.tv_sec << std::endl;
// Get a fn ptr to the "gettimeofday" fn
const char* fn_name = "gettimeofday\0";
void* raw_fn = ::dlsym(dynlib_handle, fn_name);
void (*fn)(struct timeval *tv, struct timezone *tz) =
reinterpret_cast<void (*)(struct timeval *tv,
struct timezone *tz)>(raw_fn);
waitFor(wait_time);
fn(&tv, NULL);
std::cout << "Fn ptr call: tv.tv_sec = "
<< tv.tv_sec << std::endl;
// Prep FFI CIF
// ffi_cif *cif = new ffi_cif;
ffi_cif cif;
uint32_t nargs = 2;
ffi_type *rtype = &ffi_type_uint32; // int is 32 bits
ffi_type **atypes = new ffi_type*[nargs];
atypes[0] = &ffi_type_pointer;
atypes[1] = &ffi_type_pointer;
// for (uint32_t i = 0; i < nargs; i++) {
// atypes[i] = &ffi_type_pointer; // TODO: implement
// }
ffi_status status =
ffi_prep_cif(&cif, FFI_DEFAULT_ABI, nargs, rtype, atypes);
if (status == FFI_OK) {
std::cout << "FFI CIF preparation is OK" << std::endl;
} else {
std::cout << "FFI CIF preparation failed, exiting"
<< std::endl;
return -1;
}
// Call fn with FFI
struct timeval* ptr_tv = &tv;
ffi_arg result = 0;
void *args[nargs];
args[0] = &ptr_tv;
args[1] = NULL;
// for (int i = 0; i < nargs; i++) {
// args[i] = NULL; // TODO: implement
// }
// void (*function)() =
// reinterpret_cast<void (*)()>(raw_fn);
waitFor(wait_time);
// ffi_call(&cif, function, &result_value, args);
ffi_call(&cif, FFI_FN(gettimeofday), &result, args);
// ffi_call(&cif, (void (*)())rand, &result_value, args);
// ffi_call(&cif, (void (*)())raw_fn, &result_value, args);
// fn(&tv, NULL);
std::cout << "After dynamic FFI call: tv.tv_sec = "
<< tv.tv_sec << std::endl;
std::cout << "Test completed successfully!" << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment