Last active
August 29, 2015 14:21
-
-
Save jjpe/96f33585d8986fceb0e5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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