Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | added struct types as defined in ffcall, as 't' and 'T' based on pointers with explicit size. !! only for imported functions currently. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
d91d2ed6865fecd368902289a13ade97 |
User & Date: | grable 2018-10-31 22:34:17.928 |
Original Comment: | added struct types as defined in ffcall as 't' and 'T' based on pointers with explicit size. |
Context
2018-10-31
| ||
22:37 | removed some old todos check-in: 73ad0dee58 user: grable tags: trunk | |
22:34 | added struct types as defined in ffcall, as 't' and 'T' based on pointers with explicit size. !! only for imported functions currently. check-in: d91d2ed686 user: grable tags: trunk | |
20:16 | changes for testing callback typetags check-in: 87ae944ab1 user: grable tags: trunk | |
Changes
Changes to jimff-call.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | /**************************************************************************************************** * jimff - jimtcl function symbols * */ // helper macro for calling avcall_start & vacall_start using the type enums instead of the named macros #define av_start( LIST, FUNC, RADDR, TYPE) \ avcall_start( &(LIST), (LIST)._av_alist_flexarray._av_m_args, \ &(LIST)._av_alist_flexarray._av_m_args[__AV_ALIST_WORDS], \ (__avword(*)())(FUNC), (RADDR), (TYPE), __AV_START_FLAGS) #define DPFLAGS(t) (((t) == 'P') ? JIMFF_DYNAMIC_POINTER_FLAGS : 0) static int prepare_call( struct jimff_context* ctx, av_alist* avlist, const struct jimff_symbol* sym, int argc, Jim_Obj* const argv[], union jimff_result* result) { union jimff_result tmp; struct { const char* p; int l; } str; char* errmsg; int errlen; #define AV (*avlist) // handle blitzmax Long results via pointer argument if(sym->typeinfo.typetag[0] == 'q' || sym->typeinfo.typetag[0] == 'Q') { av_start( AV, sym->addr, NULL, JIMFF_TYPE_VOID); av_ptr( AV, union jimff_result*, result); } else { av_start( AV, sym->addr, result, sym->typeinfo.returntype); } | > > > > > > > > > > > > > > > | > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | /**************************************************************************************************** * jimff - jimtcl function symbols * */ // this is the size of stack buffer used to hold structure results #define JIMFF_MAXIMUM_STRUCT_SIZE 1024 // helper macro for calling avcall_start & vacall_start using the type enums instead of the named macros #define av_start( LIST, FUNC, RADDR, TYPE) \ avcall_start( &(LIST), (LIST)._av_alist_flexarray._av_m_args, \ &(LIST)._av_alist_flexarray._av_m_args[__AV_ALIST_WORDS], \ (__avword(*)())(FUNC), (RADDR), (TYPE), __AV_START_FLAGS) #define av_start_struct( LIST, FUNC, SIZE, RADDR) \ avcall_start_struct( &(LIST), (LIST)._av_alist_flexarray._av_m_args, \ &(LIST)._av_alist_flexarray._av_m_args[__AV_ALIST_WORDS], \ (__avword(*)())(FUNC), (SIZE), 0, (RADDR), __AV_START_FLAGS) #define DPFLAGS(t) (((t) == 'P') ? JIMFF_DYNAMIC_POINTER_FLAGS : 0) static int prepare_call( struct jimff_context* ctx, av_alist* avlist, const struct jimff_symbol* sym, int argc, Jim_Obj* const argv[], union jimff_result* result) { union jimff_result tmp; struct { const char* p; int l; } str; char* errmsg; int errlen; #define AV (*avlist) int numptrs = 0; int numcbs = 0; // handle blitzmax Long results via pointer argument if(sym->typeinfo.typetag[0] == 'q' || sym->typeinfo.typetag[0] == 'Q') { av_start( AV, sym->addr, NULL, JIMFF_TYPE_VOID); av_ptr( AV, union jimff_result*, result); } else if(sym->typeinfo.returntype == JIMFF_TYPE_STRUCT) { av_start_struct( AV, sym->addr, sym->typeinfo.pointersizes[0], result); numptrs++; } else { av_start( AV, sym->addr, result, sym->typeinfo.returntype); } if(sym->typeinfo.typetag[0] == 'x') numcbs++; else if(sym->typeinfo.returntype == JIMFF_TYPE_VOIDP) numptrs++; int arg = 0; const char* t; for( t = sym->typeinfo.typetag + 1; ; t++) { if(arg >= argc) goto done_with_args; switch(*t) { case '\0': goto done_with_args; |
︙ | ︙ | |||
89 90 91 92 93 94 95 | case 'f': case 'd': if(Jim_GetDouble( ctx->interp, argv[arg], &tmp.d) != JIM_OK) return JIM_ERR; if(*t == 'd') av_double( AV, tmp.d); else av_float( AV, (float)tmp.d); break; | > | > > > > | < < < < < < < < < | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | case 'f': case 'd': if(Jim_GetDouble( ctx->interp, argv[arg], &tmp.d) != JIM_OK) return JIM_ERR; if(*t == 'd') av_double( AV, tmp.d); else av_float( AV, (float)tmp.d); break; case 'p': case 'P': { int size; void* p; if(*t == 'T') p = jimff_forget_pointer( ctx, argv[arg], &size, sym->typeinfo.pointersizes[numptrs]); else p = jimff_getpointer( ctx, argv[arg], &size, 0); if(size == -1) goto err_invalid_pointer; if(sym->typeinfo.pointersizes[numptrs] && sym->typeinfo.pointersizes[numptrs] != size) goto err_invalid_ptrsize; numptrs++; av_ptr( AV, void*, p); break; } case 'x': { struct jimff_callback* cb = jimff_getcallback( ctx, argv[arg]); if(!cb || !(cb->flags & JIMFF_FLAG_REGISTERED)) goto err_invalid_callback; |
︙ | ︙ | |||
145 146 147 148 149 150 151 152 153 154 155 156 157 158 | if(Jim_GetWide( ctx->interp, argv[arg], &tmp.w) == JIM_OK) av_longlong( AV, tmp.w); else if(Jim_GetDouble( ctx->interp, argv[arg], &tmp.d) == JIM_OK) av_double( AV, tmp.d); else { str.p = Jim_GetString( argv[arg], &str.l); av_longlong( AV, (str.l > 0) ? (long long)(intptr_t)str.p : 0); } break; } arg++; } done_with_args: if(*t != 0 || arg < argc) goto err_invalid_args; | > > > > > > > > > > > > > > > | 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | if(Jim_GetWide( ctx->interp, argv[arg], &tmp.w) == JIM_OK) av_longlong( AV, tmp.w); else if(Jim_GetDouble( ctx->interp, argv[arg], &tmp.d) == JIM_OK) av_double( AV, tmp.d); else { str.p = Jim_GetString( argv[arg], &str.l); av_longlong( AV, (str.l > 0) ? (long long)(intptr_t)str.p : 0); } break; case 't': case 'T': { int size; void* p; if(*t == 'T') p = jimff_forget_pointer( ctx, argv[arg], &size, sym->typeinfo.pointersizes[numptrs]); else p = jimff_getpointer( ctx, argv[arg], &size, 0); if(size == -1) goto err_invalid_pointer; if(sym->typeinfo.pointersizes[numptrs] != size) goto err_invalid_ptrsize; avcall_arg_struct( avlist, size, 4, p); numptrs++; break; } } arg++; } done_with_args: if(*t != 0 || arg < argc) goto err_invalid_args; |
︙ | ︙ | |||
168 169 170 171 172 173 174 | errmsg = Jim_Alloc(JIMFF_ERRMSG_MAXLEN); errlen = snprintf( errmsg, JIMFF_ERRMSG_MAXLEN, JIMFF_NAMESPACE_NAME ": argument #%d \"%s\" is not a valid callback", (1 + arg), Jim_String(argv[arg])); Jim_SetResult( ctx->interp, Jim_NewStringObjNoAlloc( ctx->interp, errmsg, errlen)); return JIM_ERR; err_invalid_callback_typetag: errmsg = Jim_Alloc(JIMFF_ERRMSG_MAXLEN); | | | | 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | errmsg = Jim_Alloc(JIMFF_ERRMSG_MAXLEN); errlen = snprintf( errmsg, JIMFF_ERRMSG_MAXLEN, JIMFF_NAMESPACE_NAME ": argument #%d \"%s\" is not a valid callback", (1 + arg), Jim_String(argv[arg])); Jim_SetResult( ctx->interp, Jim_NewStringObjNoAlloc( ctx->interp, errmsg, errlen)); return JIM_ERR; err_invalid_callback_typetag: errmsg = Jim_Alloc(JIMFF_ERRMSG_MAXLEN); errlen = snprintf( errmsg, JIMFF_ERRMSG_MAXLEN, JIMFF_NAMESPACE_NAME ": argument #%d \"%s\" callback has invalid typetag, expected \"%s\"", (1 + arg), Jim_String(argv[arg]), sym->typeinfo.callbacks[numcbs]); Jim_SetResult( ctx->interp, Jim_NewStringObjNoAlloc( ctx->interp, errmsg, errlen)); return JIM_ERR; err_invalid_pointer: errmsg = Jim_Alloc(JIMFF_ERRMSG_MAXLEN); errlen = snprintf( errmsg, JIMFF_ERRMSG_MAXLEN, JIMFF_NAMESPACE_NAME ": argument #%d \"%s\" is not a valid pointer", (1 + arg), Jim_String(argv[arg])); Jim_SetResult( ctx->interp, Jim_NewStringObjNoAlloc( ctx->interp, errmsg, errlen)); return JIM_ERR; err_invalid_ptrsize: errmsg = Jim_Alloc(JIMFF_ERRMSG_MAXLEN); errlen = snprintf( errmsg, JIMFF_ERRMSG_MAXLEN, JIMFF_NAMESPACE_NAME ": argument #%d \"%s\" pointer is not of valid size, expected %d", (1 + arg), Jim_String(argv[arg]), sym->typeinfo.pointersizes[numptrs]); Jim_SetResult( ctx->interp, Jim_NewStringObjNoAlloc( ctx->interp, errmsg, errlen)); return JIM_ERR; #undef AV } JIMFF_API Jim_Obj* jimff_newresult( struct jimff_context* ctx, const struct jimff_symbol* sym, const union jimff_result* result) { |
︙ | ︙ | |||
216 217 218 219 220 221 222 | case 'Z': { Jim_Obj* obj = Jim_NewStringObj( ctx->interp, result->Z ?: "", -1); //TODO: is it correct to free Z return values? free(result->Z); return obj; } default: | | < | > > > > | 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 | case 'Z': { Jim_Obj* obj = Jim_NewStringObj( ctx->interp, result->Z ?: "", -1); //TODO: is it correct to free Z return values? free(result->Z); return obj; } default: return jimff_newpointer( ctx, result->p, sym->typeinfo.pointersizes[0], DPFLAGS(sym->typeinfo.typetag[0])); } case JIMFF_TYPE_STRUCT: { void* p = malloc(sym->typeinfo.pointersizes[0]); memcpy( p, result, sym->typeinfo.pointersizes[0]); return jimff_newpointer( ctx, p, sym->typeinfo.pointersizes[0], JIMFF_DYNAMIC_POINTER_FLAGS); } } return ctx->interp->emptyObj; } JIMFF_API int jimff_prepare_call( struct jimff_context* ctx, av_alist* avlist, const struct jimff_symbol* sym, int argc, Jim_Obj* const argv[], union jimff_result* result) { assert( ctx ); assert( avlist ); |
︙ | ︙ | |||
258 259 260 261 262 263 264 | } JIMFF_API int jimff_call( struct jimff_context* ctx, const struct jimff_symbol* sym, int argc, Jim_Obj* const argv[]) { assert( ctx ); assert( sym ); av_alist avlist; | > | > > | | | 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | } JIMFF_API int jimff_call( struct jimff_context* ctx, const struct jimff_symbol* sym, int argc, Jim_Obj* const argv[]) { assert( ctx ); assert( sym ); av_alist avlist; union { union jimff_result result; char bytes[JIMFF_MAXIMUM_STRUCT_SIZE]; } buffer = { 0 }; if(prepare_call( ctx, &avlist, sym, argc, argv, &buffer.result) != JIM_OK) return JIM_ERR; if(ctx->cberror) { Jim_DecrRefCount( ctx->interp, ctx->cberror); ctx->cberror = NULL; } av_call(avlist); if(ctx->cberror != NULL) { Jim_DecrRefCount( ctx->interp, ctx->cberror); Jim_SetResult( ctx->interp, ctx->cberror); ctx->cberror = NULL; return JIM_ERR; } Jim_SetResult( ctx->interp, jimff_newresult( ctx, sym, &buffer.result)); return JIM_OK; } #undef DPFLAGS |
Changes to jimff.c.
︙ | ︙ | |||
121 122 123 124 125 126 127 128 129 130 131 132 133 134 | case 'f': return JIMFF_TYPE_FLOAT; case 'd': return JIMFF_TYPE_DOUBLE; case 'p': case 'P': case 'x': case 'z': case 'Z': return JIMFF_TYPE_VOIDP; default: return 0; } } //NOTE: checks if a typetag string is valid, compresses it in the process and stores it in result, allso stores the returntype, returns 1=success or 0=failure static int jimff_validate_typetag( const char* typetag, struct jimff_typeinfo* typeinfo) { assert( typetag ); | > > | 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | case 'f': return JIMFF_TYPE_FLOAT; case 'd': return JIMFF_TYPE_DOUBLE; case 'p': case 'P': case 'x': case 'z': case 'Z': return JIMFF_TYPE_VOIDP; case 't': case 'T': return JIMFF_TYPE_STRUCT; default: return 0; } } //NOTE: checks if a typetag string is valid, compresses it in the process and stores it in result, allso stores the returntype, returns 1=success or 0=failure static int jimff_validate_typetag( const char* typetag, struct jimff_typeinfo* typeinfo) { assert( typetag ); |
︙ | ︙ | |||
143 144 145 146 147 148 149 | int mode = 0; char* tmp; char* end; int size; int numptrsizes = 0; int numcallbacks = 0; int lastwasp = 0; | | > | 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | int mode = 0; char* tmp; char* end; int size; int numptrsizes = 0; int numcallbacks = 0; int lastwasp = 0; int lastwasx = 0; int lastwast = 0; //TODO: define this magic "1 result + 126 arguments + zero terminator" somewhere int ptrsizes[128]; char* callbacks[128]; char buffer[128]; char cbuffer[128]; for( ;; typetag++) { |
︙ | ︙ | |||
169 170 171 172 173 174 175 | ch = *(++typetag); if(ch == '\n') break; if(ch == '\0') goto done; } break; case '0' ... '9': | | | | 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | ch = *(++typetag); if(ch == '\n') break; if(ch == '\0') goto done; } break; case '0' ... '9': if(!lastwasp && !lastwast) return 0; // error size = strtol( typetag, &end, 0); if(end == typetag) return 0; // error typetag = end - 1; ptrsizes[numptrsizes-1] = size; break; case '(': if(!lastwasx) return 0; // error mode = 1; clen = 0; break; case ')': if(mode != 1) return 0; // error mode = 0; if(clen == 0) cbuffer[clen++] = 'v'; // default to void result if empty () |
︙ | ︙ | |||
199 200 201 202 203 204 205 | if(!gotrtype) { typeinfo->returntype = type; gotrtype = 1; } else { argc++; } buffer[len++] = ch; | | | | 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | if(!gotrtype) { typeinfo->returntype = type; gotrtype = 1; } else { argc++; } buffer[len++] = ch; if((lastwasp = (ch == 'p' || ch == 'P')) || (lastwast = (ch == 't' || ch == 'T'))) { ptrsizes[numptrsizes++] = 0; } else if(lastwasx = (ch == 'x')) { callbacks[numcallbacks++] = 0; } } else if(mode == 1) { cbuffer[clen++] = ch; } } else { return 0; // error |
︙ | ︙ |
Changes to jimff.h.
︙ | ︙ | |||
61 62 63 64 65 66 67 | signed long long w, q; // JIMFF_TYPE_LONGLONG unsigned long long W, Q; // JIMFF_TYPE_ULONGLONG float f; // JIMFF_TYPE_FLOAT double d; // JIMFF_TYPE_DOUBLE callback_t x; // JIMFF_TYPE_VOIDP const char* z; // JIMFF_TYPE_VOIDP char* Z; // JIMFF_TYPE_VOIDP | | > | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | signed long long w, q; // JIMFF_TYPE_LONGLONG unsigned long long W, Q; // JIMFF_TYPE_ULONGLONG float f; // JIMFF_TYPE_FLOAT double d; // JIMFF_TYPE_DOUBLE callback_t x; // JIMFF_TYPE_VOIDP const char* z; // JIMFF_TYPE_VOIDP char* Z; // JIMFF_TYPE_VOIDP void* p, *P; // JIMFF_TYPE_STRUCT void* t, *T; // JIMFF_TYPE_STRUCT }; // argument union for jimff_import_symbol() union jimff_argument { const char* typetag; char* typetag_c; int size; |
︙ | ︙ |
Changes to jimff_test.tcl.
1 2 3 4 5 6 | lappend auto_path . package require jimff jimff ff | | | > | < | | < < | > > > > | > > > > > > > > > > > | > > | | < < | | | | | > | | | < | > | > > > | | | > > | > > | > > > > | < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | lappend auto_path . package require jimff jimff ff ff::load test_lib.dll # structs as arguments ff::import test_Point vt8 ;# struct Point { int x; int y; } ff::import test_Symbol vt16 ;# struct Symbol { int id; int flags; const char* name; int length; } ff::import test_Buffer vt20 ;# struct Buffer { int length; char bytes[16]; } # structs as results ff::import result_Point t8ii ff::import result_Symbol t16iizi ff::import result_Buffer t20ip # for messing structs as pointers ff::import read_int ipi ff::import {read_int read_ptr} ppi ff::import write_int vpii ff::import {write_int write_ptr} vpip ff::import {__strdup strdup} Pz ff::import {__strlen strlen} ip # testing struct Point argument, size=8 set point [ff::pointer -alloc 8] write_int $point 0 100 write_int $point 4 200 test_Point $point # testing struct Symbol argument, size=16 set name [strdup "symbol"] ff::pointer -size $name [strlen $name] set symbol [ff::pointer -alloc 16] write_int $symbol 0 1 write_int $symbol 4 0x55 write_ptr $symbol 8 $name write_int $symbol 12 [ff::pointer -size $name] test_Symbol $symbol # testing struct Buffer argument, size=20 set data "Hello World!\0" set buffer [ff::pointer -alloc 20] write_int $buffer 0 [string length $data] ff::write $buffer 4 $data test_Buffer $buffer # testing struct Point result, size=8 set rpoint [result_Point 100 200] if {$rpoint ne ""} { puts "result_Point [read_int $rpoint 0], [read_int $rpoint 4]" } # testing struct Symbol result, size=16 set rsymbol [result_Symbol 1 0x55 "symbol" 6] if {$rsymbol ne ""} { puts "result_Symbol [read_int $rsymbol 0] [format 0x%X [read_int $rsymbol 4]] \"[ff::gets [read_ptr $rsymbol 8]]\"([read_int $rsymbol 12])" } # testing struct Buffer result, size=20 set bytes [strdup "Hello World!\0"] set rbuffer [result_Buffer 13 $bytes] if {$rbuffer ne ""} { puts "result_Buffer [read_int $rbuffer 0] \"[ff::gets $rbuffer 4]\"" } |
Added jimff_test_callbacks.tcl.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | lappend auto_path . package require jimff jimff ff # returns symbol and typetag if imported/registered proc find-symbol {{type -function} name} { set n [ff::info $type -typetags] set i [lsearch $n $name] if {$i >= 0} { lrange $n $i $i+1 } else { return "symbol $type \"$name\" not found" } } set lib [ff::load test_lib.dll] ff::import -function $lib {__malloc malloc} Pi ff::import -function $lib {__strcpy strcpy} ppz ff::import -function $lib {__strcat strcat} ppz ff::import -function $lib {__free free} vP ff::import -function test_callback vzx(iizd) set test_1 [ff::callback test_1 iizd] puts [find-symbol -function test_callback] puts [find-symbol -callback test_1] set p [malloc 64] ff::pointer -size $p 64 strcpy $p "Hello" strcat $p " World!" puts p=[ff::gets $p] puts gets->s=[ff::gets $p 6 s] puts s=$s proc test_1 {i z f} { puts "\ti=$i" puts "\tz=\"$z\"" puts "\tf=$f" expr $i + 1 } test_callback "message" $test_1 |
Added jimff_test_structs.tcl.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | lappend auto_path . package require jimff jimff ff ff::load test_lib.dll # structs as arguments ff::import test_Point vt8 ;# struct Point { int x; int y; } ff::import test_Symbol vt16 ;# struct Symbol { int id; int flags; const char* name; int length; } ff::import test_Buffer vt20 ;# struct Buffer { int length; char bytes[16]; } # structs as results ff::import result_Point t8ii ff::import result_Symbol t16iizi ff::import result_Buffer t20ip # for messing structs as pointers ff::import read_int ipi ff::import {read_int read_ptr} ppi ff::import write_int vpii ff::import {write_int write_ptr} vpip ff::import {__strdup strdup} Pz ff::import {__strlen strlen} ip # testing struct Point argument, size=8 set point [ff::pointer -alloc 8] write_int $point 0 100 write_int $point 4 200 test_Point $point # testing struct Symbol argument, size=16 set name [strdup "symbol"] ff::pointer -size $name [strlen $name] set symbol [ff::pointer -alloc 16] write_int $symbol 0 1 write_int $symbol 4 0x55 write_ptr $symbol 8 $name write_int $symbol 12 [ff::pointer -size $name] test_Symbol $symbol # testing struct Buffer argument, size=20 set data "Hello World!\0" set buffer [ff::pointer -alloc 20] write_int $buffer 0 [string length $data] ff::write $buffer 4 $data test_Buffer $buffer # testing struct Point result, size=8 set rpoint [result_Point 100 200] if {$rpoint ne ""} { puts "result_Point [read_int $rpoint 0], [read_int $rpoint 4]" } # testing struct Symbol result, size=16 set rsymbol [result_Symbol 1 0x55 "symbol" 6] if {$rsymbol ne ""} { puts "result_Symbol [read_int $rsymbol 0] [format 0x%X [read_int $rsymbol 4]] \"[ff::gets [read_ptr $rsymbol 8]]\"([read_int $rsymbol 12])" } # testing struct Buffer result, size=20 set bytes [strdup "Hello World!\0"] set rbuffer [result_Buffer 13 $bytes] if {$rbuffer ne ""} { puts "result_Buffer [read_int $rbuffer 0] \"[ff::gets $rbuffer 4]\"" } |
Changes to test_lib.c.
1 2 3 4 5 | #include <stdio.h> #include <stdlib.h> #include <string.h> | > > > | | | | | | | | | | | | | | | | | | | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | #include <stdio.h> #include <stdlib.h> #include <string.h> #define TESTAPI __declspec(dllexport) TESTAPI void print( const char* s) { puts(s); } TESTAPI long long test( void* x) { printf( "0x%p\n", x); return 0xCAFEF00DDEADBABELL; } typedef intptr_t (*callback_fn)(); TESTAPI void test_callback( const char* msg, callback_fn callback) { printf("begin test_callback %s\n", msg); printf( "result=%d\n", callback( 1, "2", 3.0)); printf( "end\n"); } TESTAPI int test_var_i = 100; TESTAPI float test_var_f = 12.3; TESTAPI const char* test_var_z = "Hello World!"; TESTAPI const char* test_var_p = "Another string!?"; TESTAPI char test_array[1024] = "Hello, this is an array of words defined in C\n" "It has several strings seperated by newlines\n" "And ending in a zero terminator"; TESTAPI int read_int( void* src, int offs) { return *(int*)(src + offs); } TESTAPI void write_int( void* dst, int offs, int val) { *(int*)(dst + offs) = val; } TESTAPI char* read_str( void* src, int offs, int len) { char* dst = malloc(len + 1); memcpy( dst, src + offs, len); ((char*)dst)[len] = '\0'; return dst; } TESTAPI void write_str( void* dst, int offs, void* src, int len) { memcpy( dst + offs, src, len); ((char*)dst)[offs + len] = '\0'; } TESTAPI void* __malloc( size_t size) { return malloc(size); } TESTAPI void* __realloc( void* p, size_t size) { return realloc( p, size); } TESTAPI void __free( void* p) { free(p); } TESTAPI char* __strdup( const char* s) { return strdup(s); } TESTAPI int __strlen( const char* s) { return strlen(s); } TESTAPI char* __strcpy( char* dst, const char* src) { return strcpy( dst, src); } TESTAPI char* __strncpy( char* dst, const char* src, int len) { return strncpy( dst, src, len); } TESTAPI char* __strcat( char* dst, const char* src) { return strcat( dst, src); } TESTAPI int __strcmp( const char* dst, const char* src) { return strcmp( dst, src); } TESTAPI int __strncmp( const char* dst, const char* src, int len) { return strncmp( dst, src, len); } TESTAPI char* __strchr( const char* s, int ch) { return strchr( s, ch); } TESTAPI char* __strrchr( const char* s, int ch) { return strrchr( s, ch); } TESTAPI const char* strid( const char* p) { return p; } struct Point { int x; int y; }; struct Symbol { int id; int flags; const char* name; int length; }; struct Buffer { int length; char bytes[16]; }; TESTAPI void test_Point( struct Point point) { printf( "test_Point %d,%d\n", point.x, point.y); } TESTAPI void test_Symbol( struct Symbol symbol) { printf( "test_Symbol %d 0x%X \"%s\"(%d)\n", symbol.id, symbol.flags, symbol.name, symbol.length); } TESTAPI void test_Buffer( struct Buffer buffer) { printf( "test_Buffer %d \"%.16s\"\n", buffer.length, buffer.bytes); } TESTAPI struct Point result_Point( int x, int y) { struct Point point = { .x = x, .y = y }; return point; } TESTAPI struct Symbol result_Symbol( int id, int flags, const char* name, int length) { struct Symbol symbol = { .id = id, .flags = flags, .name = name, .length = length }; return symbol; } TESTAPI struct Buffer result_Buffer( int length, char* bytes) { struct Buffer buffer = { .length = length }; memcpy( buffer.bytes, bytes, length); return buffer; } |