Module: c-ffi-test Author: Peter Benson Copyright: Original Code is Copyright (c) 1995-2004 Functional Objects, Inc. All rights reserved. License: Functional Objects Library Public License Version 1.0 Dual-license: GNU Lesser General Public License Warranty: Distributed WITHOUT WARRANTY OF ANY KIND define c-struct end; define c-struct slot slot-1 :: ; slot slot-2 :: ; pointer-type-name: , c-name: "subliminal"; end; define c-pointer-type => ; define c-struct slot max-1 :: , address-getter: max-1* ; slot max-2 :: , address-getter: max-2*; array slot max-3 :: , length: 7, address-getter: max-3* ; // bitfield slot max-4 :: , width: 4; // bitfield slot max-5 :: , width: 12; slot max-6 :: , address-getter: max-6*, setter: #f; slot max-7 :: , address-getter: max-7*; pointer-type-name: ; end; define c-function simplest-foreign-function c-name: "simplest_foreign_function"; end; define c-function ffi-no-result parameter p1 :: ; c-name: "ffi_no_result"; end; define c-function ffi-no-parameters result r :: ; c-name: "ffi_no_parameters"; end; define c-function increment-unsigned-long parameter x :: ; result r :: ; c-name: "incr_unsigned_long"; end; define c-function increment-signed-long parameter x :: ; result r :: ; c-name: "incr_signed_long"; end; define c-function increment-unsigned-int parameter x :: ; result r :: ; c-name: "incr_unsigned_int"; end; define c-function increment-signed-int parameter x :: ; result r :: ; c-name: "incr_signed_int"; end; define c-function increment-unsigned-short parameter x :: ; result r :: ; c-name: "incr_unsigned_short"; end; define c-function increment-signed-short parameter x :: ; result r :: ; c-name: "incr_signed_short"; end; define c-function increment-unsigned-char parameter x :: ; result r :: ; c-name: "incr_unsigned_char"; end; define c-function increment-signed-char parameter x :: ; result r :: ; c-name: "incr_signed_char"; end; /* define c-function increment-char parameter x :: ; result r :: ; c-name: "incr_char"; end; */ /* /// used?? define c-function ffi1 input parameter p1 :: ; parameter p2 :: ; output parameter p3 :: ; input output parameter p4 :: ; input output parameter p5 :: ; // !@#$ is this meaningful??? output parameter p6 :: ; // !@#$ how about this? result r :: ; c-name: "ffi1"; end; */ /// called from the C tests define c-callable-wrapper simple-callable of method () => () values() end c-name: "call_me"; end; define sealed method a-function () => (); format-out("From dylan: calling call_me_too\n"); values(); end; /// called from the C tests define c-callable-wrapper simple-callable2 of a-function c-name: "call_me_too"; end; /// called from C /// Be very careful to get correspondence right with C code. define c-callable-wrapper more-interesting-callable of method (p1 :: , p2 :: , p4 :: , p5 :: , p6 :: ) => (r, p3, p4, p5) check-equal("slot value of struct passed into dylan", p6.slot-1, 171717); check-equal("parameter 1 passed into interesting callable ", p1, 1); check-equal("parameter 2 passed into interesting callable", p2, 2); check-equal("parameter 4 passed into interesting callable", p4, 4); check-equal("parameter 5 passed into interesting callable", p5, 5); p6.slot-1 := #xfffff00; values(p4, p1, p2, p4) end input parameter p1 :: ; parameter p2 :: ; output parameter p3 :: ; input output parameter p4 :: ; input output parameter p5 :: ; parameter p6 :: ; result r :: ; c-name: "call_me_more"; end; define c-callable-wrapper another-interesting-callable of method (p1 :: , p2 :: , p3 :: , p4 :: , p5 :: , p6 :: ) => (r :: ) values(p1) end input parameter p1 :: ; parameter p2 :: ; input parameter p3 :: ; input parameter p4 :: ; input parameter p5 :: ; parameter p6 :: ; result r :: ; c-name: "call_me_more2"; end; // Do some define c-pointer-type's // one with a pointer-type define c-pointer-type => ; // probably doesn't have a pointer type. define c-pointer-type => ; // definitely doesn't have a pointer type. define c-pointer-type => ; define c-mapped-subtype () map , import-function: method (x) x * 2 end, export-function: method (x) truncate/(x, 2) end; pointer-type ; end; /// A couple of variables for the c-variable-test define c-address $foos-address :: c-name: "foo"; end; define c-variable foo-value :: c-name: "foo"; end; /// try some things with a variable defined via define c-variable define test variable-address-test (description: "Variable Address Tests") check-equal("set c-address", (pointer-value($foos-address) := 1), 1); check-equal("c-address value", pointer-value($foos-address), 1); check-equal("c-address value from c-variable", foo-value(), 1); check-equal("set c-variable: %s should be %s", (foo-value() := 777), 777); check-equal("c-address value 777", pointer-value($foos-address), 777); check-equal("c-variable value 777", foo-value(), 777); // !@#$ need more tests that check for agreement with C end; /// try some C-struct in different ways /// Could always use some more tests here. define test c-struct-test (description: "C-Struct Tests") format-out("minimal-size: %s", size-of()); check-equal(" struct size", struct-minimal-size(), size-of()); format-out("maximal-size: %s", size-of()); check-equal(" struct size", struct-maximal-size(), size-of()); let minimal-struct = make(); check-equal("set simple struct-slot", (minimal-struct.slot-1 := 777), 777); check-equal("simple struct slot value", minimal-struct.slot-1, 777); check-equal( "set struct simple address valued slot", minimal-struct.slot-2 := $foos-address, $foos-address); check-equal("struct simple address valued slot value", pointer-address($foos-address), pointer-address(minimal-struct.slot-2)); check-equal("stuct set pointer value address valued slot", pointer-value(minimal-struct.slot-2) := 12345, 12345); check-equal("struct pointer value check alias", foo-value(), pointer-value(minimal-struct.slot-2)); check-equal("struct pointer value check value", pointer-value(minimal-struct.slot-2), 12345); check-equal("define c-pointer-type does correct aliasing", , ); let maximal-struct = make(); // do some tests here that deal with maximal // !@#$ Need more tests to see if accessors get the same thing as C code // for corresponding C structs end; /// Try some C functions in some diffetent ways. /// this could always use more tests. define test c-function-test (description: "C Function Tests") format-out("Running c-function tests\n"); for (i from 0 below (ash(1, 8 * size-of()) - 2) by 17) check-equal("c-function unsigned char increment", increment-unsigned-char(i), i + 1); end; for(i from 0 below (ash(1, (8 * size-of()) - 1) - 2) by 17) check-equal("c-function signed char increment", increment-signed-char(i), i + 1); check-equal("c-function signed char negative increment", increment-signed-char(- i), (- i) + 1); end; for(i from 0 below (ash(1, 8 * size-of()) - 2) by 17) check-equal("c-function unsigned short increment", increment-unsigned-short(i), i + 1); end; for(i from 0 below (ash(1, (8 * size-of()) - 1) - 2) by 17) check-equal("c-function signed short increment", increment-signed-short(i), i + 1); check-equal("c-function signed short negative increment", increment-signed-short(- i), (- i) + 1); end; // !@#$ do more here end; /// --------- /// C string tests /// This just calls the c-callable function below define c-function c-string-value parameter str :: ; parameter offset :: ; result r :: ; c-name: "c_string_value"; end; /// Treat X as a C-string and return the OFFSETth element define c-callable-wrapper $c-string-value of method (x :: , offset :: ) => (r :: ); pointer-value(x, index: offset); end parameter x :: ; parameter offset :: ; result r :: ; c-name: "c_string_value"; end; /// This just calls the c-callable function below define c-function c-string-value-setter parameter new :: ; parameter str :: ; parameter offset :: ; result r :: ; c-name: "c_string_value_setter"; end; /// Treat X as a C-string and set the OFFSETth element to NEW define c-callable-wrapper $c-string-value-setter of method (new :: , x :: , offset :: ) => (r :: ); pointer-value(x, index: offset) := new; end parameter new :: ; parameter x :: ; parameter offset :: ; result r :: ; c-name: "c_string_value_setter"; end; /// check-a-c-string /// This set of tests modifies the string and accesses it through a /// foreign function, ans via element to make sure that every view of it /// is correct. define function check-a-c-string (name-string, a-string, seed) => (); for(i from 0 below size(a-string)) let this-char = as(, as(, seed) + i); check-equal(concatenate(name-string, " c-string get value from alias before"), c-string-value(a-string, i), a-string[i]); check-equal(concatenate(name-string, " c-string set value"), c-string-value(a-string, i) := this-char, this-char); check-equal(concatenate(name-string, " c-string set value"), c-string-value(a-string, i), this-char); check-equal(concatenate(name-string, " c-string get value alias"), a-string[i], this-char); check-equal(concatenate(name-string, " c-string get value from alias"), c-string-value(a-string, i), a-string[i]); end; end; /// c-string-test /// make sure that s behave as strings and collections, and that /// views onto a as a from a foreign function /// all correspond. define test c-string-test () format-out("Running c-string tests\n"); let a-string = shallow-copy("This is a test string"); check-a-c-string("", a-string, 'A'); let c-string = #f; check-true("Create a C-string with map-as", instance?(c-string := map-as(, identity, a-string), )); check-equal("size works on c-strings", size(a-string), size(c-string)); for(item in a-string, index from 0 below size(a-string)) check-equal("elements of c-string", item, c-string[index]); end; for(item in c-string, index from 0 below size(c-string)) check-equal("elements of c-string forward-iteration", item, a-string[index]); end; check-a-c-string("", c-string, 'B'); end; /// macros and tests to just check that all the functions and classes /// defined by the c-ffi exist. define macro check-class { check-class(?base:name) } => { check-true(concatenate("the class exists"), instance?("", )) } end macro; define macro check-classes { check-classes ?base-names:* end } => { ?base-names } base-names: { } => { } { ?base:name, ... } => { check-class(?base); ... } end; define macro check-function { check-function(?base:name) } => { check-true(concatenate("the function ", ?"base", " exists"), instance?(?base, )) } end macro; define macro check-functions { check-functions ?base-names:* end } => { ?base-names } base-names: { } => { } { ?base:name, ... } => { check-function(?base); ... } end; define test c-types-test (description: "C Types Tests") format-out("Running c-types tests\n"); /// check that all of these things are classes /// All of the names below are wrapped in '` check-classes value, void, int, unsigned-int, signed-int, raw-int, raw-unsigned-int, raw-signed-int, unsafe-int, unsafe-unsigned-int, unsafe-signed-int, both-int, both-unsigned-int, both-signed-int, long, unsigned-long, signed-long, raw-long, raw-unsigned-long, raw-signed-long, unsafe-long, unsafe-unsigned-long, unsafe-signed-long, both-long, both-unsigned-long, both-signed-long, short, unsigned-short, signed-short, raw-short, raw-unsigned-short, raw-signed-short, unsafe-short, unsafe-unsigned-short, unsafe-signed-short, both-short, both-unsigned-short, both-signed-short, char, unsigned-char, signed-char, raw-char, raw-unsigned-char, raw-signed-char, unsafe-char, unsafe-unsigned-char, unsafe-signed-char, both-char, both-unsigned-char, both-signed-char, number, float, double, // long-double, pointer, void*, statically-typed-pointer, untyped-pointer, struct, union, function-pointer, dylan-object end; /// check that all of these things are functions check-functions size-of, alignment-of, pointer-address, null-pointer, null-pointer?, referenced-type, pointer-value, pointer-value-setter, C-unsigned-char-at, C-signed-char-at, C-char-at, C-unsigned-char-at-setter, C-signed-char-at-setter, C-char-at-setter, C-unsigned-short-at, C-signed-short-at, C-short-at, C-unsigned-short-at-setter, C-signed-short-at-setter, C-short-at-setter, C-unsigned-long-at, C-signed-long-at, C-long-at, C-unsigned-long-at-setter, C-signed-long-at-setter, C-long-at-setter, C-unsigned-int-at, C-signed-int-at, C-int-at, C-unsigned-int-at-setter, C-signed-int-at-setter, C-int-at-setter end; end; /// ask C what it thinks the size of the minimal struct is. define c-function struct-minimal-size result r :: ; c-name: "struct_minimal_size"; end; /// ask C what it thinks the size of the maximal struct is. define c-function struct-maximal-size result r :: ; c-name: "struct_maximal_size"; end; //------- // for bug 217 define constant = ; define c-pointer-type => ; define c-function SQLAllocEnv output parameter one :: ; result value :: ; c-name: "SQLAllocEnv"; end c-function; define test bug-217 () format-out("Running bug-217 tests\n"); let (success :: , henv :: ) = SQLAllocEnv(); check-equal("bug 217 got correct success code", success, 37); check-true("bug 217 henv should be a ", instance?(henv, )); end; // // ------------- // tests for bug 321 define c-union slot union-1 :: ; slot union-2 :: ; slot union-3 :: ; slot union-4 :: ; end; define c-struct slot struct-pad-1 :: , getter: #f, setter: #f; slot union-struct :: ; slot struct-pad-2 :: , getter: #f, setter: #f; pointer-type-name: ; end; define c-function union-tester-1 parameter arg :: ; result r :: ; c-name: "union_tester_1"; end; define c-function union-tester-1-setter parameter new :: ; parameter arg :: ; c-name: "union_tester_1_setter" end; define c-function union-tester-2 parameter arg :: ; result r :: ; c-name: "union_tester_2"; end; define c-function union-tester-2-setter parameter new :: ; parameter arg :: ; c-name: "union_tester_2_setter" end; define c-function union-tester-3 parameter arg :: ; result r :: ; c-name: "union_tester_3"; end; define c-function union-tester-3-setter parameter new :: ; parameter arg :: ; c-name: "union_tester_3_setter" end; define c-function union-tester-4 parameter arg :: ; result r :: ; c-name: "union_tester_4"; end; define c-function union-tester-4-setter parameter new :: ; parameter arg :: ; c-name: "union_tester_4_setter" end; define test bug-321 () let struct = make(); union-struct(struct).union-1 := #xffff; check-equal("bug 321 accessor value 1, #xffff", union-struct(struct).union-1, #xffff); check-equal("bug 321 c-funf value 1, #xffff", union-tester-1(struct), #xffff); union-tester-1(struct) := #xffff; check-equal("bug 321 accessor second value 1, #xffff", union-struct(struct).union-1, #xffff); check-equal("bug 321 c-func second value 1, #xffff", union-tester-1(struct), #xffff); union-struct(struct).union-1 := 0; check-equal("bug 321 accessor value 1, 0", union-struct(struct).union-1, 0); check-equal("bug 321 c-funf value 1, 0", union-tester-1(struct), 0); union-tester-1(struct) := 0; check-equal("bug 321 accessor second value 1, 0", union-struct(struct).union-1, 0); check-equal("bug 321 c-func second value 1, 0", union-tester-1(struct), 0); union-struct(struct).union-2 := -1; check-equal("bug 321 accessor value 2, -1", union-struct(struct).union-2, -1); check-equal("bug 321 c-funf value 2, -1", union-tester-2(struct), -1); union-tester-2(struct) := -1; check-equal("bug 321 accessor second value 2, -1", union-struct(struct).union-2, -1); check-equal("bug 321 c-func second value 2, -1", union-tester-2(struct), -1); union-struct(struct).union-2 := 0; check-equal("bug 321 accessor value 2, 0", union-struct(struct).union-2, 0); check-equal("bug 321 c-funf value 2, 0", union-tester-2(struct), 0); union-tester-2(struct) := 0; check-equal("bug 321 accessor second value 2, 0", union-struct(struct).union-2, 0); check-equal("bug 321 c-func second value 2, 0", union-tester-2(struct), 0); union-struct(struct).union-3 := #xff; check-equal("bug 321 accessor value 3, #xff", union-struct(struct).union-3, #xff); check-equal("bug 321 c-funf value 3, #xff", union-tester-3(struct), #xff); union-tester-3(struct) := #xff; check-equal("bug 321 accessor second value 3, #xff", union-struct(struct).union-3, #xff); check-equal("bug 321 c-func second value 3, #xff", union-tester-3(struct), #xff); union-struct(struct).union-3 := 0; check-equal("bug 321 accessor value 3, 0", union-struct(struct).union-3, 0); check-equal("bug 321 c-funf value 3, 0", union-tester-3(struct), 0); union-tester-3(struct) := 0; check-equal("bug 321 accessor second value 3, 0", union-struct(struct).union-3, 0); check-equal("bug 321 c-func second value 3, 0", union-tester-3(struct), 0); union-struct(struct).union-4 := -1; check-equal("bug 321 accessor value 4, -1", union-struct(struct).union-4, -1); check-equal("bug 321 c-funf value 4, -1", union-tester-4(struct), -1); union-tester-4(struct) := -1; check-equal("bug 321 accessor second value 4, -1", union-struct(struct).union-4, -1); check-equal("bug 321 c-func second value 4, -1", union-tester-4(struct), -1); union-struct(struct).union-4 := 0; check-equal("bug 321 accessor value 4, 0", union-struct(struct).union-4, 0); check-equal("bug 321 c-funf value 4, 0", union-tester-4(struct), 0); union-tester-4(struct) := 0; check-equal("bug 321 accessor second value 4, 0", union-struct(struct).union-4, 0); check-equal("bug 321 c-func second value 4, 0", union-tester-4(struct), 0); end; // // ------------- // tests for bug 290 define c-pointer-type => ; define variable *arg-vec* :: = make(, element-count: 2); define test bug-290 () check-true("bug 290 pointer value setter works", pointer-value(*arg-vec*, index: 1) := null-pointer()); end; // // ------------- // tests for bug 313 define c-function mix-it-up input output parameter inout :: ; result value :: ; c-name: "mix_it_up"; end; define test bug-313 () let (a :: , b :: ) = mix-it-up(7); check-equal("bug 313 mix it up value 1", a, 7 + 1); check-equal("bug 313 mix it up value 2", b, 7 + 7); end; // // ------------- // tests for bug 17 define C-struct slot foo :: ; end; define C-pointer-type => ; define c-subtype () slot fff :: , init-value: 5; end; define test bug-17 () check-true("bug 17 make regular pointer", instance?(make(), )); // this works fine check-true("bug 17 make pointer subtype", instance?(make(), )); // fails end; // // ------------- // tests for bug 134 define C-struct slot LowPart-value :: ; slot HighPart-value :: ; end; define C-union slot lVal-value :: ; slot bVal-value :: ; slot iVal-value :: ; slot cyVal-value :: ; slot ptr-value :: ; end; define test bug-134 () check-true("bug 134 union has full size", size-of() >= size-of()); check-true("bug 134 large-integer has full size", size-of() >= size-of() + size-of()); end; // // ------------- // tests for bug 213 define c-struct slot whatever :: ; pointer-type-name: ; end C-struct; define test bug-213 () check-true("bug 213 make returns", instance?(make(), )); end; // // ------------- // tests for bug 209 define method betty (a :: ) a * a; end method; define c-callable-wrapper wilma of betty parameter a :: ; result r :: ; c-name: "betty"; end c-callable-wrapper; define c-function call-betty parameter a :: ; result r :: ; c-name: "betty"; end; define test bug-209 () check-equal("bug 209 call betty", call-betty(2), 4); end; // // ------------- // tests for bug 289 define c-function puts-289 parameter str :: ; result len :: ; c-name: "puts"; end; define test bug-289 () check-true("Bug 289 puts works", puts-289("a string")); end; // // ------------- // tests for bug 394 define C-struct bitfield slot bAppReturnCode-value :: , width: 8; bitfield slot reserved-value :: , width: 6; bitfield slot fBusy-value :: , width: 1; bitfield slot fAck-value :: , width: 1; pointer-type-name: ; end C-struct ; define c-function ack-return-slot parameter dde :: ; result r :: ; c-name: "return_code_slot"; end; define c-function ack-return-slot-setter parameter v :: ; parameter dde :: ; result r :: ; c-name: "return_code_slot_set"; end; define c-function ack-reserved-slot parameter dde :: ; result r :: ; c-name: "reserved_slot"; end; define c-function ack-reserved-slot-setter parameter v :: ; parameter dde :: ; result r :: ; c-name: "reserved_slot_set"; end; define c-function ack-busy-slot parameter dde :: ; result r :: ; c-name: "busy_slot"; end; define c-function ack-busy-slot-setter parameter v :: ; parameter dde :: ; result r :: ; c-name: "busy_slot_set"; end; define c-function ack-ack-slot parameter dde :: ; result r :: ; c-name: "ack_slot"; end; define c-function ack-ack-slot-setter parameter v :: ; parameter dde :: ; result r :: ; c-name: "ack_slot_set"; end; define test bug-394 () let dde :: = make(); // use c-struct setters and getters bAppReturnCode-value(dde) := 127; check-equal("by-value ddeack return correct value", Vack-return-slot(dde), 127); reserved-value(dde) := 31; check-equal("by-value ddeack reserved correct value", Vack-reserved-slot(dde), 31); fBusy-value(dde) := 1; check-equal("by-value ddeack busy correct value", Vack-busy-slot(dde), 1); fAck-value(dde) := 1; check-equal("by-value ddeack ack correct value", Vack-ack-slot(dde), 1); // Use foreign function setter and c-struct getters Vack-return-slot-setter(120, dde); check-true("by-value ack return setter doesn't set", (bAppReturnCode-value(dde) ~= 120)); check-equal("by-value ack return setter leaves value alone", bAppReturnCode-value(dde), 127); Vack-reserved-slot-setter(20, dde); check-true("by-value ack reserved setter doesn't set", (Reserved-value(dde) ~= 20)); check-equal("by-value ack reserved setter leaves value alone", Reserved-value(dde), 31); Vack-busy-slot-setter(0, dde); check-true("by-value ack busy setter doesn't set", (fBusy-value(dde) ~= 0)); check-equal("by-value ack busy setter leaves value alone", fBusy-value(dde), 1); Vack-ack-slot-setter(0, dde); check-true("by-value ack ack setter doesn't set", (fAck-value(dde) ~= 0)); check-equal("by-value ack ack setter leaves value alone", fAck-value(dde), 1); end; // // ------------- // tests for indirect: option to define c-function define c-function call-indirect indirect: #t; parameter param1 :: ; result val :: ; end; define c-function gimme-a-function result fun :: ; c-name: "gimme_a_function"; end; define test c-function-indirect () let fun = gimme-a-function(); check-equal("c-function indirect option", call-indirect(fun, 7), 7); end; // // ------------- // tests for define c-struct slot object-handle :: ; pointer-type-name: ; end; define test c-dylan-object-test () let obj = pair(1, 2); // make an object register-c-dylan-object(obj); // register it let struct = make(); let handle = export-c-dylan-object(obj); object-handle(struct) := handle; check-equal(" importing handle", import-c-dylan-object(handle), obj); check-equal(" extracting handle from struct", import-c-dylan-object(object-handle(struct)), obj); // do more here. // ... unregister-c-dylan-object(obj); destroy(struct); end; // // ------------- // tests for bug 393 define function main-bug-393 () for ( i from 0 below 200 ) let buf = make(, size: 10 + i); destroy(buf); end for; #t; end main-bug-393; define test bug-393 () check-true("bug-393 try it", main-bug-393()); end; // // ------------- // tests for bug 414 define C-struct array slot width-array :: , length: 6, address-getter: width-value, getter: #f, setter: #f; pointer-type-name: ; c-name: "struct tagOleMenuGroupWidths"; end C-struct ; define test bug-414 () let menugroupwidths = make(); // should not generate any warnings when compiling, // or errors when running check-true("bug 414 no warnings or errors", menugroupwidths.width-value); destroy(menugroupwidths); end; // // ------------- // tests for passing c structs by value define c-function OMGW-width parameter struct :: ; parameter index :: ; result r :: ; c-name: "OMGW_width" end; define c-function Vack-return-slot parameter dde :: ; result r :: ; c-name: "Vreturn_code_slot"; end; define c-function Vack-return-slot-setter parameter v :: ; parameter dde :: ; result r :: ; c-name: "Vreturn_code_slot_set"; end; define c-function Vack-reserved-slot parameter dde :: ; result r :: ; c-name: "Vreserved_slot"; end; define c-function Vack-reserved-slot-setter parameter v :: ; parameter dde :: ; result r :: ; c-name: "Vreserved_slot_set"; end; define c-function Vack-busy-slot parameter dde :: ; result r :: ; c-name: "Vbusy_slot"; end; define c-function Vack-busy-slot-setter parameter v :: ; parameter dde :: ; result r :: ; c-name: "Vbusy_slot_set"; end; define c-function Vack-ack-slot parameter dde :: ; result r :: ; c-name: "Vack_slot"; end; define c-function Vack-ack-slot-setter parameter v :: ; parameter dde :: ; result r :: ; c-name: "Vack_slot_set"; end; define test struct-by-value () let dde :: = make(); // use c-struct setters and getters bAppReturnCode-value(dde) := 127; check-equal("by-value return code setter and getter", bAppReturnCode-value(dde), 127); reserved-value(dde) := 31; check-equal("by-value reserved setter and getter", reserved-value(dde), 31); fBusy-value(dde) := 1; check-equal("by-value busy setter and getter", fBusy-value(dde), 1); fAck-value(dde) := 1; check-equal("by-value ack setter and getter", fAck-value(dde), 1); // Use foreign function setter and c-struct getters ack-return-slot(dde) := 120; check-equal("by-value return code ff setter and getter", bAppReturnCode-value(dde), 120); ack-reserved-slot(dde) := 20; check-equal("by-value reserved ff setter and getter", reserved-value(dde), 20); ack-busy-slot(dde) := 0; check-equal("by-value busy ff setter and getter", fBusy-value(dde), 0); ack-ack-slot(dde) := 0; check-equal("by-value ack ff setter and getter", fAck-value(dde), 0); let widths = make(); for (i from 0 below 6) pointer-value(width-value(widths), index: i) := i + 47; check-equal("by-value array-slot values", OMGW-width(widths, i), i + 47); end; end; // -------------- // top level test suite. define suite c-ffi-suite () test variable-address-test; test c-struct-test; test c-function-test; test c-string-test; test c-types-test; test bug-217; test bug-321; test bug-290; test bug-313; test bug-17; test bug-134; test bug-213; test bug-209; test bug-289; test bug-394; test c-function-indirect; test c-dylan-object-test; test bug-393; test bug-414; test struct-by-value end suite c-ffi-suite; /// The dylan top level for the tests /// This gets called via a C-callable function from C define method run-dylan-tests () => (); *debug?* := #f; perform-suite(c-ffi-suite); end; define c-callable-wrapper run-dylan-tests-pointer of run-dylan-tests c-name: "run_dylan_tests"; end; /// invokes the C test top level define c-function run-tests-from-c c-name: "run_tests_from_c" end; /// signed integer identity function callable from C define c-callable-wrapper dylan-identity of identity parameter j :: ; result j :: ; c-name: "dylan_int_identity" end; define constant always-one = method () as(, 1) end; define c-callable-wrapper dylan-always-one of always-one result j :: ; c-name: "dylan_always_one" end; // ------------- /// set up bookkeeping around running the tests define method c-ffi-test-begin () => (); format-out("Starting to run C FFI tests\n"); end; define c-variable c-failure-count :: c-name: "failure_count"; end; define c-variable c-test-count :: c-name: "test_count"; end; /// testworks doesn't know about the tests we have run in C /// so we can report them here. define method c-ffi-test-final-report (abort) => (); format-out("%s running C FFI tests\n", if (abort) "Aborted" else "Finished" end); let c-lossage-count = c-failure-count(); format-out("Encountered %= failures from C\n", c-lossage-count); format-out("out of a total of %= tests from C.\n", c-test-count()); end; /// Top level for the whole library define method run-da-tests() => (); let abort = #t; block () c-ffi-test-begin(); run-tests-from-c(); abort := #f; cleanup c-ffi-test-final-report(abort); end; end; run-da-tests(); //-------------