@@ -553,6 +553,8 @@ def handle_class(sdkver, classnode):
553
553
for alias in aliases [iface_version ]:
554
554
constructors .write (" {\" %s\" , &create_%s}, /* alias */\n " % (alias , winclassname ))
555
555
556
+ generate_c_api_thunk_tests (winclassname , methods , method_names )
557
+
556
558
557
559
generated_struct_handlers = []
558
560
cpp_files_need_close_brace = []
@@ -757,6 +759,190 @@ def generate_flatapi_c():
757
759
758
760
f .write ("#endif\n " )
759
761
762
+ def generate_c_api_method_test (f , header , thunks_c , class_name , method_name , method ):
763
+ thunk_params = get_capi_thunk_params (method )
764
+ f .write ("\n init_thunk(t, this_ptr_value, %s_%s, %s);\n " % (class_name , method_name , thunk_params ))
765
+ f .write (" " )
766
+ header .write ("\n " )
767
+ thunks_c .write ("\n " )
768
+
769
+ returns_record = method .result_type .get_canonical ().kind == clang .cindex .TypeKind .RECORD
770
+ if returns_record :
771
+ f .write ("%s *" % strip_ns (method .result_type .spelling ))
772
+ header .write ("%s *" % strip_ns (method .result_type .spelling ))
773
+ thunks_c .write ("%s *" % strip_ns (method .result_type .spelling ))
774
+ else :
775
+ f .write ("%s " % strip_ns (method .result_type .spelling ))
776
+ header .write ("%s " % strip_ns (method .result_type .spelling ))
777
+ thunks_c .write ("%s " % strip_ns (method .result_type .spelling ))
778
+ first_param = True
779
+ f .write ('(__stdcall *capi_%s_%s)(' % (class_name , method_name ))
780
+ header .write ('__thiscall %s_%s(void *_this' % (class_name , method_name ))
781
+ thunks_c .write ('__thiscall %s_%s(void *_this' % (class_name , method_name ))
782
+ if returns_record :
783
+ f .write ("%s *_r" % strip_ns (method .result_type .spelling ))
784
+ first_param = False
785
+ header .write (", %s *_r" % strip_ns (method .result_type .spelling ))
786
+ thunks_c .write (", %s *_r" % strip_ns (method .result_type .spelling ))
787
+
788
+ for param in get_params (method ):
789
+ if param .type .kind == clang .cindex .TypeKind .POINTER \
790
+ and param .type .get_pointee ().kind == clang .cindex .TypeKind .UNEXPOSED :
791
+ typename = "void *"
792
+ else :
793
+ typename = param .type .spelling .split ("::" )[- 1 ].replace ("&" , "*" );
794
+ if not first_param :
795
+ f .write (", " )
796
+ first_param = False
797
+ f .write ("%s %s" % (typename , param .spelling ))
798
+ header .write (", %s %s" % (typename , param .spelling ))
799
+ thunks_c .write (", %s %s" % (typename , param .spelling ))
800
+ f .write (") = (void *)t;\n " )
801
+ header .write (");\n " )
802
+ thunks_c .write (")\n {\n " )
803
+
804
+ thunks_c .write (" push_ptr_parameter(_this);\n " )
805
+ if returns_record :
806
+ thunks_c .write (" push_ptr_parameter(_r);\n " )
807
+ for param in get_params (method ):
808
+ param_size = param .type .get_size ()
809
+ if param .type .kind == clang .cindex .TypeKind .POINTER \
810
+ or param .type .spelling .endswith ("&" ) \
811
+ or param .type .spelling == "vr::glSharedTextureHandle_t" :
812
+ typename = "ptr"
813
+ elif param .type .spelling == "bool" :
814
+ typename = "bool"
815
+ elif param .type .spelling == "float" :
816
+ typename = "float"
817
+ elif param .type .spelling == "vr::HmdRect2_t" :
818
+ typename = "HmdRect2"
819
+ elif param .type .spelling == "vr::HmdVector2_t" :
820
+ typename = "HmdVector2"
821
+ elif param .type .spelling == "vr::HmdVector3_t" :
822
+ typename = "HmdVector3"
823
+ elif param .type .spelling == "vr::HmdColor_t" :
824
+ typename = "HmdColor"
825
+ elif param_size == 8 :
826
+ typename = "uint64"
827
+ elif param_size == 4 or param_size == 2 :
828
+ typename = "uint32"
829
+ else :
830
+ typename = "unknown"
831
+ thunks_c .write (" push_%s_parameter(%s);\n " % (typename , param .spelling ))
832
+ if method .result_type .kind != clang .cindex .TypeKind .VOID :
833
+ thunks_c .write (" return 0;\n " )
834
+ thunks_c .write ("}\n " )
835
+
836
+ parameter_checks = []
837
+ def add_parameter_check (typename , value ):
838
+ parameter_checks .append ("check_%s_parameter(\" %s_%s\" , %s)" % (typename , class_name , method_name , value ))
839
+ add_parameter_check ("ptr" , "this_ptr_value" )
840
+ f .write ("\n " )
841
+ f .write (" clear_parameters();\n " )
842
+ f .write (" capi_%s_%s(" % (class_name , method_name ))
843
+ first_param = True
844
+ if returns_record :
845
+ f .write ("data_ptr_value" )
846
+ first_param = False
847
+ add_parameter_check ("ptr" , "data_ptr_value" )
848
+ for i , param in enumerate (get_params (method )):
849
+ i += 1
850
+ param_size = param .type .get_size ()
851
+ if param .type .kind == clang .cindex .TypeKind .POINTER \
852
+ or param .type .spelling .endswith ("&" ) \
853
+ or param .type .spelling == "vr::glSharedTextureHandle_t" :
854
+ v = "(void *)%s" % i
855
+ add_parameter_check ("ptr" , v )
856
+ elif param .type .spelling == "bool" :
857
+ v = "1"
858
+ add_parameter_check ("bool" , v )
859
+ elif param .type .spelling == "float" :
860
+ v = "%s.0f" % i
861
+ add_parameter_check ("float" , v )
862
+ elif param .type .spelling == "vr::HmdRect2_t" :
863
+ v = "DEFAULT_RECT" ;
864
+ add_parameter_check ("HmdRect2" , v )
865
+ elif param .type .spelling == "vr::HmdVector2_t" :
866
+ v = "DEFAULT_VECTOR2" ;
867
+ add_parameter_check ("HmdVector2" , v )
868
+ elif param .type .spelling == "vr::HmdVector3_t" :
869
+ v = "DEFAULT_VECTOR3" ;
870
+ add_parameter_check ("HmdVector3" , v )
871
+ elif param .type .spelling == "vr::HmdColor_t" :
872
+ v = "DEFAULT_COLOR" ;
873
+ add_parameter_check ("HmdColor" , v )
874
+ elif param_size == 8 :
875
+ v = str (i )
876
+ add_parameter_check ("uint64" , v )
877
+ elif param_size == 4 or param_size == 2 :
878
+ v = str (i )
879
+ add_parameter_check ("uint32" , v )
880
+ if not first_param :
881
+ f .write (", " )
882
+ first_param = False
883
+ f .write (v )
884
+ f .write (");\n " )
885
+ for c in parameter_checks :
886
+ f .write (" %s;\n " % c )
887
+
888
+ def generate_c_api_thunk_tests (winclassname , methods , method_names ):
889
+ class_name = re .sub (r'^win[A-Za-z]+_' , '' , winclassname )
890
+
891
+ filename = "tests/capi_thunks_autogen.h"
892
+ file_exists = os .path .isfile (filename )
893
+ header = open (filename , "a" )
894
+ if not file_exists :
895
+ header .write ("""/* This file is auto-generated, do not edit. */
896
+ #include <stdarg.h>
897
+ #include <stdint.h>
898
+
899
+ #include "windef.h"
900
+ #include "winbase.h"
901
+
902
+ #include "cxx.h"
903
+ #include "flatapi.h"
904
+ #include "vrclient_defs.h"
905
+
906
+ #include "capi_thunks.h"
907
+ """ )
908
+ header .write ("\n void test_capi_thunks_%s(void);\n " % class_name )
909
+
910
+ filename = "tests/capi_thunks_autogen.c"
911
+ file_exists = os .path .isfile (filename )
912
+ thunks_c = open (filename , "a" )
913
+ if not file_exists :
914
+ thunks_c .write ("""/* This file is auto-generated, do not edit. */
915
+ #include "capi_thunks_autogen.h"
916
+ """ )
917
+
918
+ filename = "tests/capi_thunks_tests_autogen.c"
919
+ file_exists = os .path .isfile (filename )
920
+ with open (filename , "a" ) as f :
921
+ if not file_exists :
922
+ f .write ("""/* This file is auto-generated, do not edit. */
923
+ #include "capi_thunks_autogen.h"
924
+ """ )
925
+ f .write ("\n void test_capi_thunks_%s(void)\n {\n " % class_name )
926
+ f .write (" struct thunk *t = alloc_thunks(1);\n " );
927
+ for i in range (len (methods )):
928
+ generate_c_api_method_test (f , header , thunks_c , class_name , method_names [i ], methods [i ])
929
+ f .write (" VirtualFree(t, 0, MEM_RELEASE);\n " )
930
+ f .write ("}\n " )
931
+
932
+ filename = "tests/main_autogen.c"
933
+ file_exists = os .path .isfile (filename )
934
+ with open (filename , "a" ) as f :
935
+ if not file_exists :
936
+ f .write ("""/* This file is auto-generated, do not edit. */
937
+ #include "capi_thunks_autogen.h"
938
+
939
+ #include <stdio.h>
940
+
941
+ int main(void)
942
+ {
943
+ """ )
944
+ f .write (" test_capi_thunks_%s();\n " % class_name )
945
+
760
946
761
947
#clang.cindex.Config.set_library_file("/usr/lib/llvm-3.8/lib/libclang-3.8.so.1");
762
948
@@ -806,4 +992,8 @@ def generate_flatapi_c():
806
992
m = open (f , "a" )
807
993
m .write ("\n }\n " )
808
994
995
+ with open ("tests/main_autogen.c" , "a" ) as f :
996
+ f .write (" printf(\" All tests executed.\\ n\" );\n " )
997
+ f .write ("}\n " )
998
+
809
999
generate_flatapi_c ()
0 commit comments