@needs_dlfcn
def test_dlfcn_funcs(self):
    self.prep_dlfcn_lib()
    lib_src = '\n      #include <assert.h>\n      #include <stdio.h>\n      #include <string.h>\n\n      typedef void (*voidfunc)();\n      typedef void (*intfunc)(int);\n\n      void callvoid(voidfunc f) { f(); }\n      void callint(voidfunc f, int x) { f(x); }\n\n      void void_0() { printf("void 0\\n"); }\n      void void_1() { printf("void 1\\n"); }\n      voidfunc getvoid(int i) {\n        switch(i) {\n          case 0: return void_0;\n          case 1: return void_1;\n          default: return NULL;\n        }\n      }\n\n      void int_0(int x) { printf("int 0 %d\\n", x); }\n      void int_1(int x) { printf("int 1 %d\\n", x); }\n      intfunc getint(int i) {\n        switch(i) {\n          case 0: return int_0;\n          case 1: return int_1;\n          default: return NULL;\n        }\n      }\n      '
    self.set_setting('EXPORTED_FUNCTIONS', ['_callvoid', '_callint', '_getvoid', '_getint'])
    dirname = self.get_dir()
    self.build_dlfcn_lib(lib_src, dirname, os.path.join(dirname, 'liblib.c'))
    self.prep_dlfcn_main()
    src = '\n      #include <assert.h>\n      #include <stdio.h>\n      #include <dlfcn.h>\n\n      typedef void (*voidfunc)();\n      typedef void (*intfunc)(int);\n\n      typedef void (*voidcaller)(voidfunc);\n      typedef void (*intcaller)(intfunc, int);\n\n      typedef voidfunc (*voidgetter)(int);\n      typedef intfunc (*intgetter)(int);\n\n      void void_main() { printf("void_main.\\n"); }\n      void int_main(int x) { printf("int_main %d\\n", x); }\n\n      int main() {\n        printf("go\\n");\n        void *lib_handle;\n        lib_handle = dlopen("liblib.so", RTLD_NOW);\n        assert(lib_handle != NULL);\n\n        voidcaller callvoid = (voidcaller)dlsym(lib_handle, "callvoid");\n        assert(callvoid != NULL);\n        callvoid(void_main);\n\n        intcaller callint = (intcaller)dlsym(lib_handle, "callint");\n        assert(callint != NULL);\n        callint(int_main, 201);\n\n        voidgetter getvoid = (voidgetter)dlsym(lib_handle, "getvoid");\n        assert(getvoid != NULL);\n        callvoid(getvoid(0));\n        callvoid(getvoid(1));\n\n        intgetter getint = (intgetter)dlsym(lib_handle, "getint");\n        assert(getint != NULL);\n        callint(getint(0), 54);\n        callint(getint(1), 9000);\n\n        assert(getint(1000) == NULL);\n\n        puts("ok");\n        return 0;\n      }\n      '
    self.set_setting('EXPORTED_FUNCTIONS', ['_main', '_malloc'])
    self.do_run(src, 'go\nvoid_main.\nint_main 201\nvoid 0\nvoid 1\nint 0 54\nint 1 9000\nok\n', force_c=True)
@needs_dlfcn
def test_dlfcn_funcs(self):
    self.prep_dlfcn_lib()
    lib_src = '\n      #include <assert.h>\n      #include <stdio.h>\n      #include <string.h>\n\n      typedef void (*voidfunc)();\n      typedef void (*intfunc)(int);\n\n      void callvoid(voidfunc f) { f(); }\n      void callint(voidfunc f, int x) { f(x); }\n\n      void void_0() { printf("void 0\\n"); }\n      void void_1() { printf("void 1\\n"); }\n      voidfunc getvoid(int i) {\n        switch(i) {\n          case 0: return void_0;\n          case 1: return void_1;\n          default: return NULL;\n        }\n      }\n\n      void int_0(int x) { printf("int 0 %d\\n", x); }\n      void int_1(int x) { printf("int 1 %d\\n", x); }\n      intfunc getint(int i) {\n        switch(i) {\n          case 0: return int_0;\n          case 1: return int_1;\n          default: return NULL;\n        }\n      }\n      '
    self.set_setting('EXPORTED_FUNCTIONS', ['_callvoid', '_callint', '_getvoid', '_getint'])
    dirname = self.get_dir()
    self.build_dlfcn_lib(lib_src, dirname, os.path.join(dirname, 'liblib.c'))
    self.prep_dlfcn_main()
    src = '\n      #include <assert.h>\n      #include <stdio.h>\n      #include <dlfcn.h>\n\n      typedef void (*voidfunc)();\n      typedef void (*intfunc)(int);\n\n      typedef void (*voidcaller)(voidfunc);\n      typedef void (*intcaller)(intfunc, int);\n\n      typedef voidfunc (*voidgetter)(int);\n      typedef intfunc (*intgetter)(int);\n\n      void void_main() { printf("void_main.\\n"); }\n      void int_main(int x) { printf("int_main %d\\n", x); }\n\n      int main() {\n        printf("go\\n");\n        void *lib_handle;\n        lib_handle = dlopen("liblib.so", RTLD_NOW);\n        assert(lib_handle != NULL);\n\n        voidcaller callvoid = (voidcaller)dlsym(lib_handle, "callvoid");\n        assert(callvoid != NULL);\n        callvoid(void_main);\n\n        intcaller callint = (intcaller)dlsym(lib_handle, "callint");\n        assert(callint != NULL);\n        callint(int_main, 201);\n\n        voidgetter getvoid = (voidgetter)dlsym(lib_handle, "getvoid");\n        assert(getvoid != NULL);\n        callvoid(getvoid(0));\n        callvoid(getvoid(1));\n\n        intgetter getint = (intgetter)dlsym(lib_handle, "getint");\n        assert(getint != NULL);\n        callint(getint(0), 54);\n        callint(getint(1), 9000);\n\n        assert(getint(1000) == NULL);\n\n        puts("ok");\n        return 0;\n      }\n      '
    self.set_setting('EXPORTED_FUNCTIONS', ['_main', '_malloc'])
    self.do_run(src, 'go\nvoid_main.\nint_main 201\nvoid 0\nvoid 1\nint 0 54\nint 1 9000\nok\n', force_c=True)