1# Copyright (c) 2018 The Chromium Embedded Framework Authors. All rights 2# reserved. Use of this source code is governed by a BSD-style license that 3# can be found in the LICENSE file. 4 5from __future__ import absolute_import 6from cef_parser import * 7from file_util import * 8import os 9 10# Other headers that export C API functions. 11OTHER_HEADERS = [ 12 'cef_api_hash.h', 13 'cef_version.h', 14 'internal/cef_logging_internal.h', 15 'internal/cef_string_list.h', 16 'internal/cef_string_map.h', 17 'internal/cef_string_multimap.h', 18 'internal/cef_string_types.h', 19 'internal/cef_thread_internal.h', 20 'internal/cef_time.h', 21 'internal/cef_trace_event_internal.h', 22] 23 24 25def make_libcef_dll_dylib_impl_parts(name, retval, args): 26 # Split arguments into types and names. 27 arg_types = '' 28 arg_names = '' 29 for arg in args: 30 if len(arg_types) > 0: 31 arg_types += ', ' 32 arg_names += ', ' 33 pos = arg.rfind(' ') 34 arg_types += arg[0:pos] 35 arg_names += arg[pos + 1:] 36 37 typedef = 'typedef %s (*%s_ptr)(%s);\n' % (retval, name, arg_types) 38 39 declare = '%s_ptr %s;\n' % (name, name) 40 41 init = ' INIT_ENTRY(%s);' % name 42 43 impl = """NO_SANITIZE("cfi-icall") %s %s(%s) { 44 %sg_libcef_pointers.%s(%s); 45} 46 47""" % (retval, name, ', '.join(args), 'return ' 48 if retval != 'void' else '', name, arg_names) 49 50 return (typedef, declare, init, impl) 51 52 53def make_libcef_dll_dylib_impl_func(func): 54 name = func.get_capi_name() 55 parts = func.get_capi_parts([]) 56 retval = parts['retval'] 57 args = parts['args'] 58 return make_libcef_dll_dylib_impl_parts(name, retval, args) 59 60 61def make_libcef_dll_dylib_impl(header): 62 filenames = [] 63 includes = [ 64 '#include "include/base/cef_compiler_specific.h"', 65 '#include "include/wrapper/cef_library_loader.h"', 66 ] 67 ptr_typedef = '' 68 ptr_declare = '' 69 ptr_init = '' 70 ptr_impl = '' 71 72 # Include required headers for global functions. 73 for func in header.get_funcs(): 74 typedef, declare, init, impl = make_libcef_dll_dylib_impl_func(func) 75 ptr_typedef += typedef 76 ptr_declare += declare 77 ptr_init += init 78 ptr_impl += impl 79 80 filename = func.get_file_name() 81 if not filename in filenames: 82 includes.append('#include "include/capi/%s"' % func.get_capi_file_name()) 83 filenames.append(filename) 84 85 # Include required headers for static class functions. 86 allclasses = header.get_classes() 87 for cls in allclasses: 88 funcs = cls.get_static_funcs() 89 for func in funcs: 90 typedef, declare, init, impl = make_libcef_dll_dylib_impl_func(func) 91 ptr_typedef += typedef 92 ptr_declare += declare 93 ptr_init += init 94 ptr_impl += impl 95 96 if len(funcs) > 0: 97 filename = cls.get_file_name() 98 if not filename in filenames: 99 includes.append('#include "include/capi/%s"' % cls.get_capi_file_name()) 100 filenames.append(filename) 101 102 # Parse other headers. 103 root_directory = header.get_root_directory() 104 for other in OTHER_HEADERS: 105 path = os.path.join(root_directory, other) 106 content = read_file(path) 107 funcs = get_function_impls(content, 'CEF_EXPORT', False) 108 for func in funcs: 109 typedef, declare, init, impl = make_libcef_dll_dylib_impl_parts( 110 func['name'], func['retval'], func['args']) 111 ptr_typedef += typedef 112 ptr_declare += declare 113 ptr_init += init 114 ptr_impl += impl 115 116 includes.append('#include "include/%s"' % other) 117 118 # Build the final output. 119 result = get_copyright() + """ 120 121#include <dlfcn.h> 122#include <stdio.h> 123 124""" + "\n".join(sorted(includes)) + """ 125 126// GLOBAL WRAPPER FUNCTIONS - Do not edit by hand. 127 128namespace { 129 130void* g_libcef_handle = nullptr; 131 132void* libcef_get_ptr(const char* path, const char* name) { 133 void* ptr = dlsym(g_libcef_handle, name); 134 if (!ptr) { 135 fprintf(stderr, "dlsym %s: %s\\n", path, dlerror()); 136 } 137 return ptr; 138} 139 140""" + ptr_typedef + """ 141 142struct libcef_pointers { 143""" + ptr_declare + """ 144} g_libcef_pointers = {0}; 145 146#define INIT_ENTRY(name) \ 147 g_libcef_pointers.name = (name##_ptr)libcef_get_ptr(path, #name); \ 148 if (!g_libcef_pointers.name) { \ 149 return 0; \ 150 } 151 152int libcef_init_pointers(const char* path) { 153""" + ptr_init + """ 154 return 1; 155} 156 157} // namespace 158 159int cef_load_library(const char* path) { 160 if (g_libcef_handle) 161 return 0; 162 163 g_libcef_handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL | RTLD_FIRST); 164 if (!g_libcef_handle) { 165 fprintf(stderr, "dlopen %s: %s\\n", path, dlerror()); 166 return 0; 167 } 168 169 if (!libcef_init_pointers(path)) { 170 cef_unload_library(); 171 return 0; 172 } 173 174 return 1; 175} 176 177int cef_unload_library() { 178 int result = 0; 179 if (g_libcef_handle) { 180 result = !dlclose(g_libcef_handle); 181 if (!result) { 182 fprintf(stderr, "dlclose: %s\\n", dlerror()); 183 } 184 g_libcef_handle = nullptr; 185 } 186 return result; 187} 188 189""" + ptr_impl 190 return result 191 192 193def write_libcef_dll_dylib_impl(header, file): 194 newcontents = make_libcef_dll_dylib_impl(header) 195 return (file, newcontents) 196 197 198# Test the module. 199if __name__ == "__main__": 200 import sys 201 202 # Verify that the correct number of command-line arguments are provided. 203 if len(sys.argv) < 2: 204 sys.stderr.write('Usage: ' + sys.argv[0] + ' <cpp_header_dir>\n') 205 sys.exit() 206 207 cpp_header_dir = sys.argv[1] 208 209 # Create the header object. Should match the logic in translator.py. 210 header = obj_header() 211 header.set_root_directory(cpp_header_dir) 212 excluded_files = ['cef_api_hash.h', 'cef_application_mac.h', 'cef_version.h'] 213 header.add_directory(cpp_header_dir, excluded_files) 214 header.add_directory(os.path.join(cpp_header_dir, 'test')) 215 header.add_directory(os.path.join(cpp_header_dir, 'views')) 216 217 # Dump the result to stdout. 218 sys.stdout.write(make_libcef_dll_dylib_impl(header)) 219