README.md (7914B)
1 # odin-c-bindgen: Generate Odin bindings for C libraries 2 3 This generator makes it possible to quickly generate C library bindings for the Odin Programming Language. 4 5 Features: 6 - Easy to get started with. Can generate bindings from a folder of headers. 7 - Generates nice-looking bindings that retain comments. Example: [Generated Raylib bindings](https://github.com/karl-zylinski/odin-c-bindgen/blob/main/examples/raylib/raylib/raylib.odin). 8 - Simplicity. The generator is simple enough that you can modify it, should the need arise. 9 - Configurable. Easy to override types and turn enums into bit_sets, etc. More info [below](#configuration) and [in the examples](https://github.com/karl-zylinski/odin-c-bindgen/blob/main/examples/raylib/bindgen.sjson). 10 11 > If you find this generator helpful and want to say thanks, then please consider [donating](https://github.com/sponsors/karl-zylinski). 12 > 13 > Discuss and ask questions on [my Discord server](https://discord.gg/4FsHgtBmFK). 14 15 ## Requirements 16 - Odin 17 - libclang version 16 or higher 18 - On Windows: Download libclang 20.1.8 from here: https://github.com/llvm/llvm-project/releases/download/llvmorg-20.1.8/clang+llvm-20.1.8-x86_64-pc-windows-msvc.tar.xz -- Copy the following from that archive: 19 - `lib/libclang.lib` into the generator's 'libclang' folder 20 - `bin/libclang.dll` into the root of the generator (next to where the bindgen executable will end up). 21 - On Linux/mac, please install libclang. For example using `apt install libclang-dev` on Ubuntu/Debian/Mint. Anything from clang version 16 and new should work. 22 23 > [!NOTE] 24 > libclang is used for analysing the C headers and deciding what Odin code to output. 25 26 ## Getting started 27 28 1. Build the generator: `odin build src -out:bindgen.exe` (replace `.exe` with `.bin` on mac/Linux) 29 2. Make a folder. Inside it, put the C headers (`.h` files) of the library you want to generate bindings for. 30 3. Execute `bindgen the_folder` 31 4. Bindings can be found inside `the_folder/the_folder` 32 5. To get more control of how the generation happens, use a `bindgen.sjson` file to. See how in the next section, or look in the `examples` folder. 33 34 ## Configuration 35 36 Add a `bindgen.sjson` to your bindings folder. I.e. inside the folder you feed into `bindgen`. Below is an example. See the [examples folder](https://github.com/karl-zylinski/odin-c-bindgen/tree/main/examples) for more advanced examples. 37 38 > NOTE: Config uses the function/type names as found in header files. 39 40 ```sjson 41 // Inputs can be folders or files. If you provide a folder name, then the generator will look for 42 // header (.h) files inside it. The bindings will be based on those headers. For each header, 43 // you can create a `header_footer.odin` file with some additional code to append to the finished 44 // bindings. If the header is called `raylib.h` then the footer would be `raylib_footer.odin`. 45 inputs = [ 46 "input" 47 ] 48 49 // Output folder. In there you'll find one .odin file per processed header. 50 output_folder = "my_lib" 51 52 // Remove this prefix from types names (structs, enums, etc) 53 remove_type_prefix = "" 54 55 // Remove this prefix from macro names 56 remove_macro_prefix = "" 57 58 // Remove this prefix from function names (and add it as link_prefix) to the foreign group 59 remove_function_prefix = "" 60 61 // Remove this suffix from type names (such as '_t' etc) 62 remove_type_suffix = "" 63 64 // Set to true translate type names to Ada_Case 65 force_ada_case_types = false 66 67 // Single lib file to import. Will be ignored if `imports_file` is set. 68 import_lib = "my_lib.lib" 69 70 // The filename of a file that contains the foreign import declarations. In it you can do 71 // platform-specific library imports etc. The contents of it will be placed near the top of the 72 // file. 73 imports_file = "" 74 75 // `package something` to put at top of each generated Odin binding file. 76 package_name = "my_lib" 77 78 // "Old_Name" = "New_Name" 79 rename = { 80 } 81 82 // Turns an enum into a bit_set. Converts the values of the enum into appropriate values for a 83 // bit_set (translates the enum values using a log2 procedure). 84 // 85 // Note that the enum will be turned into a bit_set type. There will be a new type created that 86 // contains the actual enum, which the bit_set then references. 87 bit_setify = { 88 // "Enum_To_Turn_Into_Bitset" = "New_Enum_Type_Name" 89 } 90 91 // Completely override the definition of a type. 92 type_overrides = { 93 // "Vector2" = "[2]f32" 94 } 95 96 // Override the type of a struct field. 97 // 98 // You can also use `[^]` to augment an already existing type. 99 struct_field_overrides = { 100 // "Some_Type.some_field" = "My_Type" 101 // "Some_Other_Type.field" = "[^]" 102 // "Some_Other_Type.another_file" = "[^]cstring" 103 } 104 105 // Put these tags on the specified struct field 106 struct_field_tags = { 107 // "BoneInfo.name" = "fmt:\"s,0\"" 108 } 109 110 // Remove a specific enum member. Write the C name of the member. You can also use wildcards 111 // such as *_Count 112 remove_enum_members = [ 113 // "MAGICAL_ENUM_ALL" 114 // "_*Count" 115 ] 116 117 // Overrides the type of a procedure parameter or return value. For a parameter use the key 118 // Proc_Name.parameter_name. For a return value use the key Proc_Name. 119 // 120 // You can also use `[^]`, `#by_ptr` and `#any_int` to augment an already existing type. 121 procedure_type_overrides = { 122 // "SetConfigFlags.flags" = "ConfigFlags" 123 // "GetKeyPressed" = "KeyboardKey" 124 } 125 126 // Add in a default value to a procedure parameter. Use `Proc_Name.parameter_name` as key and 127 // write the plain-text Odin value as value. 128 // 129 // You can also add defaults for proc parameters within structs. In that case you do: 130 // `Struct_Name.proc_field.parameter_name` -- This does not currently support nested structs. 131 procedure_parameter_defaults = { 132 // "DrawTexturePro.tint" = "RED" 133 // "Some_Struct.a_field_that_is_a_proc.some_parameter" = "5" 134 } 135 136 // Put the names of declarations in here to remove them. 137 remove = [ 138 // "Some_Declaration_Name" 139 ] 140 141 // Group all procedures at the end of the file. 142 procedures_at_end = false 143 144 // Additional include paths to send into clang. While generating the bindings clang will look into 145 // this path in search for included headers. 146 clang_include_paths = [ 147 // "include" 148 ] 149 150 // Pass these compiler defines into clang. Can be used to control clang pre-processor 151 clang_defines = { 152 // "UFBX_REAL_IS_FLOAT" = "1" 153 } 154 ``` 155 156 ## FAQ and common problems 157 158 ### Why didn't my bindings generate correctly? 159 160 Please look through the list of configuration options listed above and see if they help you. Also, 161 see the the examples folder for additional inspiration. 162 163 If you fail to make any progress on generating bindings for a certain library, then submit an issue on this GitHub page and provide the headers in a zip. I'll try to help if I can find some time. 164 165 ### How can I add some extra code to a generated file? 166 167 If the source header is called `raylib.h` then add a a file called `raylib_footer.odin` next to it 168 and put your code in there. 169 170 ### How do I manually specify which libraries to load on different platforms etc? 171 172 Use `imports_file` in `bindgen.sjson`. See `examples/raylib` 173 174 ### How can I turn an enum into a bit_set? 175 176 In `bindgen.sjson`: 177 178 ``` 179 bit_setify = { 180 "your_enum" = "the_bit_set_type" 181 } 182 ``` 183 184 This will create a type `the_bit_set_type :: bit_set[your_enum; c.int`. 185 186 It will also translate the values of the enum by calculating their log2 value (that gives you the bit index instead of the integer value corresponding to that bit). 187 188 ### My headers can't find other headers in the same folder 189 190 If the generator is processing `include/some_folder/header.h` and it can't find some other header `include/some_folder/something.h`, then add `include` to the include search path by adding he following to `bindgen.sjson`: 191 192 ``` 193 clang_include_paths = [ 194 "include" 195 ] 196 ``` 197 198 ## Acknowledgements 199 200 Big thanks to [Xandaron](https://github.com/xandaron/) for figuring out a lot of the libclang stuff. 201 202 This generator was inspired by floooh's Sokol bindgen: https://github.com/floooh/sokol/tree/master/bindgen