Re: Andrea Cini's euwingui
- Posted by jimcbrown (admin) Nov 11, 2010
- 4206 views
Hi
Purely for curiosity's sake, please explain. How have they changed? How would you one write a shim that would convert? What would they convert - from / to? Has the internal structure / arrangement of the sequence changed from 3.x to 4?
Chris
The biggest change was the addition of the cleanup_ptr at the end of every structure (s1 [for sequences], d [for atoms], etc) used internally by euphoria to represent non-integer types. The code checks to see if this is NULL or not, and if not it attempts to interpret the value as an euphoria routine and calls it (runs the code of the routine). So if a 3.1 object was passed, we'd try to read pass the end of the memory for the structure. And then execute it. (But this particular issue is easy to deal with, a shim just needs add NULL to the end of the structure.)
It might not have been as easy as I thought. I wrote the following shim code, but EuWinGUI no longer crashes but doesn't seem to work either.
// libconvert.dll // tested with 4.0.0RC1's euphoria.h but this code is designed to work // with 3.1.1's euphoria.h as well #include <include/euphoria.h> #ifdef _WIN32 #define DLLEXTERN extern __declspec(dllexport) #define DLLEXPORT __declspec(dllexport) // Use Heap functions for everything. void * ddefault_heap = NULL; #include <windows.h> #define hmalloc(n) HeapAlloc((void *)ddefault_heap, 0, n) #define hfree(p) HeapFree((void *)ddefault_heap, 0, p) #define hrealloc(p, n) HeapReAlloc((void *)ddefault_heap, 0, p, n) #else #define DLLEXTERN extern #define DLLEXPORT #define hmalloc(n) malloc(n) #define hfree(p) free(p) #define hrealloc(p, n) realloc(p, n) #endif DLLEXTERN void * atom_to_v3(void * param); DLLEXTERN void * atom_to_v4(void * param); DLLEXTERN void * sequence_to_v3(void * param); DLLEXTERN void * sequence_to_v4(void * param); DLLEXTERN void * object_to_v3(void * param); DLLEXTERN void * object_to_v4(void * param); struct s1v4 { object_ptr base; long length; long ref; long postfill; void * cleanup; }; struct dv4 { double dbl; long ref; void * cleanup; }; typedef struct dv4 *dv4_ptr; typedef struct s1v4 *s1v4_ptr; #define DBL_PTR4(ob) ( (dv4_ptr) (((unsigned)(ob)) << 3) ) #define SEQ_PTR4(ob) ( (s1v4_ptr) (((unsigned)(ob)) << 3) ) struct s1v3 { object_ptr base; long length; long ref; long postfill; }; struct dv3 { double dbl; long ref; }; typedef struct dv3 *dv3_ptr; typedef struct s1v3 *s1v3_ptr; #define DBL_PTR3(ob) ( (dv3_ptr) (((unsigned)(ob)) << 3) ) #define SEQ_PTR3(ob) ( (s1v3_ptr) (((unsigned)(ob)) << 3) ) void init() { #ifdef _WIN32 if (ddefault_heap == NULL) ddefault_heap = GetProcessHeap(); //ddefault_heap = HeapCreate(0,0,0); #endif } DLLEXPORT void * atom_to_v3(void * param) { dv4_ptr d4; dv3_ptr d3; object atom = (object)param; if (IS_ATOM_INT(atom) || atom == NOVALUE) { return param; } if (!(IS_ATOM(atom))) { return NULL; } init(); d4 = DBL_PTR4(atom); d3 = (dv3_ptr)hmalloc(sizeof(struct dv3)); d3->dbl = d4->dbl; d3->ref = 2; // not safe to free, so keep forever //d4->ref--; return (void *)(MAKE_DBL(d3)); } DLLEXPORT void * atom_to_v4(void * param) { dv4_ptr d4; dv3_ptr d3; object atom = (object)param; if (IS_ATOM_INT(atom) || atom == NOVALUE) { return param; } if (!(IS_ATOM(atom))) { return NULL; } init(); d3 = DBL_PTR3(atom); d4 = (dv4_ptr)hmalloc(sizeof(struct dv4)); d4->dbl = d3->dbl; d4->ref = 2; // not safe to free, so keep forever d4->cleanup = NULL; //d3->ref--; return (void *)(MAKE_DBL(d4)); } DLLEXPORT void * sequence_to_v3(void * param) { int i; s1v4_ptr s4; s1v3_ptr s3; object atom = (object)param; if (!(IS_SEQUENCE(atom))) { return NULL; } init(); s4 = SEQ_PTR4(atom); s3 = (s1v3_ptr)hmalloc(sizeof(struct s1v3) + (s4->length + 1) * sizeof(object)); s3->ref = 2; // not safe to free, so keep forever s3->base = (object_ptr)(s3 + 1); s3->base[s4->length] = NOVALUE; for (i = 0; i < s4->length; i++) { s3->base[i] = (object)object_to_v3((void*)(s4->base[i])); } s3->length = s4->length; s3->postfill = s4->postfill; // is this right? s3->base--; // point to "0th" element //s4->ref--; return (void *)(MAKE_SEQ(s3)); } DLLEXPORT void * sequence_to_v4(void * param) { int i; s1v4_ptr s4; s1v3_ptr s3; object atom = (object)param; if (!(IS_SEQUENCE(atom))) { return NULL; } init(); s3 = SEQ_PTR3(atom); s4 = (s1v4_ptr)hmalloc(sizeof(struct s1v4) + (s3->length + 1) * sizeof(object)); s4->ref = 2; // not safe to free, so keep forever s4->base = (object_ptr)(s4 + 1); s4->base[s3->length] = NOVALUE; for (i = 0; i < s3->length; i++) { s4->base[i] = (object)object_to_v4((void*)(s3->base[i])); } s4->length = s3->length; s4->postfill = s3->postfill; // is this right? s4->cleanup = NULL; s4->base--; // point to "0th" element //s3->ref--; return (void *)(MAKE_SEQ(s4)); } DLLEXPORT void * object_to_v3(void * param) { object atom = (object)param; if (IS_ATOM_INT(atom) || atom == NOVALUE) { return param; } if (IS_SEQUENCE(atom)) { return sequence_to_v3(param); } return atom_to_v3(param); } DLLEXPORT void * object_to_v4(void * param) { object atom = (object)param; if (IS_ATOM_INT(atom) || atom == NOVALUE) { return param; } if (IS_SEQUENCE(atom)) { return sequence_to_v4(param); } return atom_to_v4(param); }
Here are the required changes to EuWinGUI.ew
AM = C_POINTER, SQ = C_POINTER --AM = E_ATOM, --SQ = E_SEQUENCE atom object_to_v3, object_to_v4, v3helper function v3_c_func(atom x, sequence p) object ret, r, q q = "" for i = 1 to length(p) do q &= 0 q[i] = c_func(object_to_v3, {p[i]}) end for ret = c_func(x, q) r = c_func(object_to_v4, {ret}) return r end function procedure v3_c_proc(atom x, sequence p) object q q = "" for i = 1 to length(p) do q &= 0 q[i] = c_func(object_to_v3, {p[i]}) end for c_proc(x, q) end procedure procedure link() v3helper = indll("LIBCONVERT.DLL") object_to_v3 = infunc(v3helper,"object_to_v3",{E_OBJECT},C_POINTER) object_to_v4 = infunc(v3helper,"object_to_v4",{C_POINTER},E_OBJECT) EWG = indll("EuWinGUI.DLL")