1# Gmsh - Copyright (C) 1997-2021 C. Geuzaine, J.-F. Remacle 2# 3# See the LICENSE.txt file in the Gmsh root directory for license information. 4# Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues. 5 6# Contributor(s): 7# Jonathan Lambrechts 8 9import textwrap 10import string 11import os 12import re 13 14 15class arg: 16 def __init__(self, name, value, python_value, julia_value, cpp_type, 17 c_type, out): 18 self.name = name 19 self.value = value 20 self.out = out 21 self.cpp = cpp_type + " " + name + ((" = " + value) if value else "") 22 self.c_arg = name 23 self.c_pre = "" 24 self.c_post = "" 25 self.c = c_type + " " + name 26 self.cwrap_arg = self.name 27 self.cwrap_pre = "" 28 self.cwrap_post = "" 29 self.python_value = python_value if python_value is not None else value 30 self.python_arg = "" 31 self.python_return = "" 32 self.python_pre = "" 33 self.julia_value = julia_value if julia_value is not None else value 34 self.julia_arg = name 35 self.julia_ctype = "" 36 self.julia_pre = "" 37 self.julia_post = "" 38 self.julia_return = name 39 self.fortran_type_post = "" 40 self.fortran_name_pre = "" 41 self.fortran_name_post = "" 42 self.texi = name + ( 43 (" = " + self.python_value) if self.python_value else "") 44 45 46# input types 47 48 49def ibool(name, value=None, python_value=None, julia_value=None): 50 a = arg(name, value, python_value, julia_value, "const bool", "const int", 51 False) 52 a.python_arg = "c_int(bool(" + name + "))" 53 a.cwrap_arg = "(int)" + name 54 a.julia_ctype = "Cint" 55 a.fortran_type = "integer(c_int), value" 56 return a 57 58 59def iint(name, value=None, python_value=None, julia_value=None): 60 a = arg(name, value, python_value, julia_value, "const int", "const int", 61 False) 62 a.python_arg = "c_int(" + name + ")" 63 a.julia_ctype = "Cint" 64 a.fortran_type = "integer(c_int), value" 65 return a 66 67 68def isize(name, value=None, python_value=None, julia_value=None): 69 a = arg(name, value, python_value, julia_value, "const std::size_t", 70 "const size_t", False) 71 a.python_arg = "c_size_t(" + name + ")" 72 a.julia_ctype = "Csize_t" 73 a.fortran_type = "integer(c_size_t), value" 74 return a 75 76 77def idouble(name, value=None, python_value=None, julia_value=None): 78 a = arg(name, value, python_value, julia_value, "const double", 79 "const double", False) 80 a.python_arg = "c_double(" + name + ")" 81 a.julia_ctype = "Cdouble" 82 a.fortran_type = "real(c_double), value" 83 return a 84 85 86def istring(name, value=None, python_value=None, julia_value=None): 87 a = arg(name, value, python_value, julia_value, "const std::string &", 88 "const char *", False) 89 a.python_arg = "c_char_p(" + name + ".encode())" 90 a.cwrap_arg = name + ".c_str()" 91 a.julia_ctype = "Ptr{Cchar}" 92 a.fortran_type = "character(len = 1, kind = c_char)" 93 a.fortran_type_post = "(*)" 94 return a 95 96 97def ivoidstar(name, value=None, python_value=None, julia_value=None): 98 a = arg(name, value, python_value, julia_value, "const void *", 99 "const void *", False) 100 a.python_arg = "c_void_p(" + name + ")" 101 a.julia_ctype = "Ptr{Cvoid}" 102 a.fortran_type = "integer(c_int)" 103 a.fortran_type_post = "(*)" 104 return a 105 106 107def ivectorint(name, value=None, python_value=None, julia_value=None): 108 if julia_value == "[]": 109 julia_value = "Cint[]" 110 a = arg(name, value, python_value, julia_value, "const std::vector<int> &", 111 "const int *", False) 112 api_name = "api_" + name + "_" 113 api_name_n = "api_" + name + "_n_" 114 a.c_pre = (" std::vector<int> " + api_name + "(" + name + ", " + name + 115 " + " + name + "_n);\n") 116 a.c_arg = api_name 117 a.c = "int * " + name + ", size_t " + name + "_n" 118 a.cwrap_pre = ("int *" + api_name + "; size_t " + api_name_n + "; " + 119 "vector2ptr(" + name + ", &" + api_name + ", &" + 120 api_name_n + ");\n") 121 a.cwrap_arg = api_name + ", " + api_name_n 122 a.cwrap_post = ns + "Free(" + api_name + ");\n" 123 a.python_pre = api_name + ", " + api_name_n + " = _ivectorint(" + name + ")" 124 a.python_arg = api_name + ", " + api_name_n 125 a.julia_ctype = "Ptr{Cint}, Csize_t" 126 a.julia_arg = "convert(Vector{Cint}, " + name + "), length(" + name + ")" 127 a.fortran_type = "integer(c_int)" 128 a.fortran_type_post = "(*)\n integer(c_size_t), value :: " + name + "_n" 129 a.fortran_name_post = ",\n & " + name + "_n" 130 return a 131 132 133def ivectorsize(name, value=None, python_value=None, julia_value=None): 134 if julia_value == "[]": 135 julia_value = "Csize_t[]" 136 a = arg(name, value, python_value, julia_value, 137 "const std::vector<std::size_t> &", "const size_t *", False) 138 api_name = "api_" + name + "_" 139 api_name_n = "api_" + name + "_n_" 140 a.c_pre = (" std::vector<std::size_t> " + api_name + "(" + name + ", " + 141 name + " + " + name + "_n);\n") 142 a.c_arg = api_name 143 a.c = "size_t * " + name + ", size_t " + name + "_n" 144 a.cwrap_pre = ("size_t *" + api_name + "; size_t " + api_name_n + "; " + 145 "vector2ptr(" + name + ", &" + api_name + ", &" + 146 api_name_n + ");\n") 147 a.cwrap_arg = api_name + ", " + api_name_n 148 a.cwrap_post = ns + "Free(" + api_name + ");\n" 149 a.python_pre = api_name + ", " + api_name_n + " = _ivectorsize(" + name + ")" 150 a.python_arg = api_name + ", " + api_name_n 151 a.julia_ctype = "Ptr{Csize_t}, Csize_t" 152 a.julia_arg = "convert(Vector{Csize_t}, " + name + "), length(" + name + ")" 153 a.fortran_type = "integer(c_size_t)" 154 a.fortran_type_post = "(*)\n integer(c_size_t), value :: " + name + "_n" 155 a.fortran_name_post = ",\n & " + name + "_n" 156 return a 157 158 159def ivectordouble(name, value=None, python_value=None, julia_value=None): 160 if julia_value == "[]": 161 julia_value = "Cdouble[]" 162 a = arg(name, value, python_value, julia_value, 163 "const std::vector<double> &", "double **", False) 164 api_name = "api_" + name + "_" 165 api_name_n = "api_" + name + "_n_" 166 a.c_pre = (" std::vector<double> " + api_name + "(" + name + ", " + 167 name + " + " + name + "_n);\n") 168 a.c_arg = api_name 169 a.c = "double * " + name + ", size_t " + name + "_n" 170 a.cwrap_pre = ("double *" + api_name + "; size_t " + api_name_n + "; " + 171 "vector2ptr(" + name + ", &" + api_name + ", &" + 172 api_name_n + ");\n") 173 a.cwrap_arg = api_name + ", " + api_name_n 174 a.cwrap_post = ns + "Free(" + api_name + ");\n" 175 a.python_pre = api_name + ", " + api_name_n + " = _ivectordouble(" + name + ")" 176 a.python_arg = api_name + ", " + api_name_n 177 a.julia_ctype = "Ptr{Cdouble}, Csize_t" 178 a.julia_arg = "convert(Vector{Cdouble}, " + name + "), length(" + name + ")" 179 a.fortran_type = "real(c_double)" 180 a.fortran_type_post = "(*)\n integer(c_size_t), value :: " + name + "_n" 181 a.fortran_name_post = ",\n & " + name + "_n" 182 return a 183 184 185def ivectorstring(name, value=None, python_value=None, julia_value=None): 186 a = arg(name, value, python_value, julia_value, 187 "const std::vector<std::string> &", "char **", False) 188 api_name = "api_" + name + "_" 189 api_name_n = "api_" + name + "_n_" 190 a.c_pre = (" std::vector<std::string> " + api_name + "(" + name + ", " + 191 name + " + " + name + "_n);\n") 192 a.c_arg = api_name 193 a.c = "char ** " + name + ", size_t " + name + "_n" 194 a.cwrap_pre = ("char **" + api_name + "; size_t " + api_name_n + "; " + 195 "vectorstring2charptrptr(" + name + ", &" + api_name + 196 ", &" + api_name_n + ");\n") 197 a.cwrap_arg = api_name + ", " + api_name_n 198 a.cwrap_post = ("for(size_t i = 0; i < " + api_name_n + "; ++i){ " + ns + 199 "Free(" + api_name + "[i]); } " + ns + "Free(" + api_name + 200 ");\n") 201 a.python_pre = api_name + ", " + api_name_n + " = _ivectorstring(" + name + ")" 202 a.python_arg = api_name + ", " + api_name_n 203 a.julia_ctype = "Ptr{Ptr{Cchar}}, Csize_t" 204 a.julia_arg = name + ", length(" + name + ")" 205 a.fortran_type = "type(c_ptr)" 206 a.fortran_type_post = "(*)\n integer(c_size_t), value :: " + name + "_n" 207 a.fortran_name_post = ",\n & " + name + "_n" 208 return a 209 210 211def ivectorpair(name, value=None, python_value=None, julia_value=None): 212 if julia_value == "[]": 213 julia_value = "Tuple{Cint,Cint}[]" 214 a = arg(name, value, python_value, julia_value, 215 "const " + ns + "::vectorpair &", "const int *", False) 216 api_name = "api_" + name + "_" 217 api_name_n = "api_" + name + "_n_" 218 a.c_pre = (" " + ns + "::vectorpair " + api_name + "(" + name + 219 "_n/2);\n" + " for(size_t i = 0; i < " + name + 220 "_n/2; ++i){\n" + " " + api_name + "[i].first = " + name + 221 "[i * 2 + 0];\n" + " " + api_name + "[i].second = " + 222 name + "[i * 2 + 1];\n" + " }\n") 223 a.c_arg = api_name 224 a.c = "int * " + name + ", size_t " + name + "_n" 225 a.cwrap_pre = ("int *" + api_name + "; size_t " + api_name_n + "; " + 226 "vectorpair2intptr(" + name + ", &" + api_name + ", &" + 227 api_name_n + ");\n") 228 a.cwrap_arg = api_name + ", " + api_name_n 229 a.cwrap_post = ns + "Free(" + api_name + ");\n" 230 a.python_pre = api_name + ", " + api_name_n + " = _ivectorpair(" + name + ")" 231 a.python_arg = api_name + ", " + api_name_n 232 a.julia_ctype = "Ptr{Cint}, Csize_t" 233 a.julia_pre = (api_name + " = collect(Cint, Iterators.flatten(" + name + 234 "))\n " + api_name_n + " = length(" + api_name + ")") 235 a.julia_arg = (api_name + ", " + api_name_n) 236 a.fortran_type = "integer(c_int)" 237 a.fortran_type_post = "(*)\n integer(c_size_t), value :: " + name + "_n" 238 a.fortran_name_post = ",\n & " + name + "_n" 239 return a 240 241 242def ivectorvectorint(name, value=None, python_value=None, julia_value=None): 243 if julia_value == "[]": 244 julia_value = "Vector{Cint}[]" 245 a = arg(name, value, python_value, julia_value, 246 "const std::vector<std::vector<int> > &", "const int **", False) 247 api_name = "api_" + name + "_" 248 api_name_n = "api_" + name + "_n_" 249 api_name_nn = "api_" + name + "_nn_" 250 a.c_pre = (" std::vector<std::vector<int> > " + api_name + "(" + name + 251 "_nn);\n" + " for(size_t i = 0; i < " + name + 252 "_nn; ++i)\n" + " " + api_name + 253 "[i] = std::vector<int>(" + name + "[i], " + name + "[i] + " + 254 name + "_n[i]);\n") 255 a.c_arg = api_name 256 a.c = ("const int ** " + name + ", const size_t * " + name + "_n, " + 257 "size_t " + name + "_nn") 258 a.cwrap_pre = ("int **" + api_name + "; size_t *" + api_name_n + ", " + 259 api_name_nn + "; " + "vectorvector2ptrptr(" + name + ", &" + 260 api_name + ", &" + api_name_n + ", &" + api_name_nn + 261 ");\n") 262 a.cwrap_arg = "(const int **)" + api_name + ", " + api_name_n + ", " + api_name_nn 263 a.cwrap_post = ("for(size_t i = 0; i < " + api_name_nn + "; ++i){ " + ns + 264 "Free(" + api_name + "[i]); } " + ns + "Free(" + api_name + 265 "); " + ns + "Free(" + api_name_n + ");\n") 266 a.python_pre = (api_name + ", " + api_name_n + ", " + api_name_nn + 267 " = _ivectorvectorint(" + name + ")") 268 a.python_arg = api_name + ", " + api_name_n + ", " + api_name_nn 269 a.julia_ctype = "Ptr{Ptr{Cint}}, Ptr{Csize_t}, Csize_t" 270 a.julia_pre = (api_name_n + " = [ length(" + name + 271 "[i]) for i in 1:length(" + name + ") ]") 272 a.julia_arg = ("convert(Vector{Vector{Cint}}," + name + "), " + 273 api_name_n + ", length(" + name + ")") 274 a.fortran_type = "type(c_ptr), intent(out)" 275 a.fortran_type_post = ("\n type(c_ptr), intent(out) :: " + name + 276 "_n\n integer(c_size_t) :: " + name + "_nn") 277 a.fortran_name_post = ",\n & " + name + "_n,\n & " + name + "_nn" 278 return a 279 280 281def ivectorvectorsize(name, value=None, python_value=None, julia_value=None): 282 if julia_value == "[]": 283 julia_value = "Vector{Csize_t}[]" 284 a = arg(name, value, python_value, julia_value, 285 "const std::vector<std::vector<std::size_t> > &", 286 "const size_t **", False) 287 api_name = "api_" + name + "_" 288 api_name_n = "api_" + name + "_n_" 289 api_name_nn = "api_" + name + "_nn_" 290 a.c_pre = (" std::vector<std::vector<std::size_t> > " + api_name + "(" + 291 name + "_nn);\n" + " for(size_t i = 0; i < " + name + 292 "_nn; ++i)\n" + " " + api_name + 293 "[i] = std::vector<std::size_t>(" + name + "[i], " + name + 294 "[i] + " + name + "_n[i]);\n") 295 a.c_arg = api_name 296 a.c = ("const size_t ** " + name + ", const size_t * " + name + "_n, " + 297 "size_t " + name + "_nn") 298 a.cwrap_pre = ("size_t **" + api_name + "; size_t *" + api_name_n + ", " + 299 api_name_nn + "; " + "vectorvector2ptrptr(" + name + ", &" + 300 api_name + ", &" + api_name_n + ", &" + api_name_nn + 301 ");\n") 302 a.cwrap_arg = "(const size_t **)" + api_name + ", " + api_name_n + ", " + api_name_nn 303 a.cwrap_post = ("for(size_t i = 0; i < " + api_name_nn + "; ++i){ " + ns + 304 "Free(" + api_name + "[i]); } " + ns + "Free(" + api_name + 305 "); " + ns + "Free(" + api_name_n + ");\n") 306 a.python_pre = (api_name + ", " + api_name_n + ", " + api_name_nn + 307 " = _ivectorvectorsize(" + name + ")") 308 a.python_arg = api_name + ", " + api_name_n + ", " + api_name_nn 309 a.julia_ctype = "Ptr{Ptr{Csize_t}}, Ptr{Csize_t}, Csize_t" 310 a.julia_pre = (api_name_n + " = [ length(" + name + 311 "[i]) for i in 1:length(" + name + ") ]") 312 a.julia_arg = ("convert(Vector{Vector{Csize_t}}," + name + "), " + 313 api_name_n + ", length(" + name + ")") 314 a.fortran_type = "type(c_ptr), intent(out)" 315 a.fortran_type_post = ("\n type(c_ptr), intent(out) :: " + name + 316 "_n\n integer(c_size_t) :: " + name + "_nn") 317 a.fortran_name_post = ",\n & " + name + "_n,\n & " + name + "_nn" 318 return a 319 320 321def ivectorvectordouble(name, value=None, python_value=None, julia_value=None): 322 if julia_value == "[]": 323 julia_value = "Vector{Cdouble}[]" 324 a = arg(name, value, python_value, julia_value, 325 "const std::vector<std::vector<double> > &", "const double**", 326 False) 327 api_name = "api_" + name + "_" 328 api_name_n = "api_" + name + "_n_" 329 api_name_nn = "api_" + name + "_nn_" 330 a.c_pre = (" std::vector<std::vector<double> > " + api_name + "(" + 331 name + "_nn);\n" + " for(size_t i = 0; i < " + name + 332 "_nn; ++i)\n" + " " + api_name + 333 "[i] = std::vector<double>(" + name + "[i], " + name + 334 "[i] + " + name + "_n[i]);\n") 335 a.c_arg = api_name 336 a.c = ("const double ** " + name + ", const size_t * " + name + "_n, " + 337 "size_t " + name + "_nn") 338 a.cwrap_pre = ("double **" + api_name + "; size_t *" + api_name_n + ", " + 339 api_name_nn + "; " + "vectorvector2ptrptr(" + name + ", &" + 340 api_name + ", &" + api_name_n + ", &" + api_name_nn + 341 ");\n") 342 a.cwrap_arg = "(const double **)" + api_name + ", " + api_name_n + ", " + api_name_nn 343 a.cwrap_post = ("for(size_t i = 0; i < " + api_name_nn + "; ++i){ " + ns + 344 "Free(" + api_name + "[i]); } " + ns + "Free(" + api_name + 345 "); " + ns + "Free(" + api_name_n + ");\n") 346 a.python_pre = (api_name + ", " + api_name_n + ", " + api_name_nn + 347 " = _ivectorvectordouble(" + name + ")") 348 a.python_arg = api_name + ", " + api_name_n + ", " + api_name_nn 349 a.julia_ctype = "Ptr{Ptr{Cdouble}}, Ptr{Csize_t}, Csize_t" 350 a.julia_pre = (api_name_n + " = [ length(" + name + 351 "[i]) for i in 1:length(" + name + ") ]") 352 a.julia_arg = ("convert(Vector{Vector{Cdouble}}," + name + "), " + 353 api_name_n + ", length(" + name + ")") 354 a.fortran_type = "type(c_ptr), intent(out)" 355 a.fortran_type_post = ("\n type(c_ptr), intent(out) :: " + 356 name + "_n\n integer(c_size_t) :: " + name + "_nn") 357 a.fortran_name_post = ",\n & " + name + "_n,\n & " + name + "_nn" 358 return a 359 360 361# output types 362 363 364class oint(arg): 365 rcpp_type = "int" 366 rc_type = "int" 367 rtexi_type = "integer value" 368 rjulia_type = "Cint" 369 fortran_type = "integer(c_int)" 370 fortran_type_post = "" 371 372 def __init__(self, name, value=None, python_value=None, julia_value=None): 373 arg.__init__(self, name, value, python_value, julia_value, "int &", 374 "int *", True) 375 api_name = "api_" + name + "_" 376 self.c_arg = "*" + name 377 self.cwrap_arg = "&" + name 378 self.python_pre = api_name + " = c_int()" 379 self.python_arg = "byref(" + api_name + ")" 380 self.python_return = api_name + ".value" 381 self.julia_ctype = "Ptr{Cint}" 382 self.julia_pre = api_name + " = Ref{Cint}()" 383 self.julia_arg = api_name 384 self.julia_return = api_name + "[]" 385 386 387class osize(arg): 388 rcpp_type = "std::size_t" 389 rc_type = "size_t" 390 rtexi_type = "size value" 391 rjulia_type = "Csize_t" 392 fortran_type = "integer(c_size_t)" 393 fortran_type_post = "" 394 395 def __init__(self, name, value=None, python_value=None, julia_value=None): 396 arg.__init__(self, name, value, python_value, julia_value, 397 "std::size_t &", "size_t *", True) 398 api_name = "api_" + name + "_" 399 self.c_arg = "*" + name 400 self.cwrap_arg = "&" + name 401 self.python_pre = api_name + " = c_size_t()" 402 self.python_arg = "byref(" + api_name + ")" 403 self.python_return = api_name + ".value" 404 self.julia_ctype = "Ptr{Csize_t}" 405 self.julia_pre = api_name + " = Ref{Csize_t}()" 406 self.julia_arg = api_name 407 self.julia_return = api_name + "[]" 408 409 410class odouble(arg): 411 rcpp_type = "double" 412 rc_type = "double" 413 rtexi_type = "floating point value" 414 rjulia_type = "Cdouble" 415 fortran_type = "real(c_double)" 416 fortran_type_post = "" 417 418 def __init__(self, name, value=None, python_value=None, julia_value=None): 419 arg.__init__(self, name, value, python_value, julia_value, "double &", 420 "double *", True) 421 api_name = "api_" + name + "_" 422 self.c_arg = "*" + name 423 self.cwrap_arg = "&" + name 424 self.python_pre = api_name + " = c_double()" 425 self.python_arg = "byref(" + api_name + ")" 426 self.python_return = api_name + ".value" 427 self.julia_ctype = "Ptr{Cdouble}" 428 self.julia_pre = api_name + " = Ref{Cdouble}()" 429 self.julia_arg = api_name 430 self.julia_return = api_name + "[]" 431 432 433def ostring(name, value=None, python_value=None, julia_value=None): 434 a = arg(name, value, python_value, julia_value, "std::string &", "char **", 435 True) 436 api_name = "api_" + name + "_" 437 a.c_pre = " std::string " + api_name + ";\n" 438 a.c_arg = api_name 439 a.c_post = " *" + name + " = strdup(" + api_name + ".c_str());\n" 440 a.cwrap_pre = "char *" + api_name + ";\n" 441 a.cwrap_arg = "&" + api_name 442 a.cwrap_post = (name + " = std::string(" + api_name + "); " + ns + 443 "Free(" + api_name + ");\n") 444 a.python_pre = api_name + " = c_char_p()" 445 a.python_arg = "byref(" + api_name + ")" 446 a.python_return = "_ostring(" + api_name + ")" 447 a.julia_ctype = "Ptr{Ptr{Cchar}}" 448 a.julia_pre = api_name + " = Ref{Ptr{Cchar}}()" 449 a.julia_arg = api_name 450 a.julia_post = name + " = unsafe_string(" + api_name + "[])" 451 a.fortran_type = "type(c_ptr)" 452 a.fortran_type_post = "(*)" 453 return a 454 455 456def ovectorint(name, value=None, python_value=None, julia_value=None): 457 a = arg(name, value, python_value, julia_value, "std::vector<int> &", 458 "int **", True) 459 api_name = "api_" + name + "_" 460 api_name_n = api_name + "n_" 461 a.c_pre = " std::vector<int> " + api_name + ";\n" 462 a.c_arg = api_name 463 a.c_post = " vector2ptr(" + api_name + ", " + name + ", " + name + "_n);\n" 464 a.c = "int ** " + name + ", size_t * " + name + "_n" 465 a.cwrap_pre = "int *" + api_name + "; size_t " + api_name_n + ";\n" 466 a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n 467 a.cwrap_post = (name + ".assign(" + api_name + ", " + api_name + " + " + 468 api_name_n + "); " + ns + "Free(" + api_name + ");\n") 469 a.python_pre = api_name + ", " + api_name_n + " = POINTER(c_int)(), c_size_t()" 470 a.python_arg = "byref(" + api_name + "), byref(" + api_name_n + ")" 471 a.python_return = "_ovectorint(" + api_name + ", " + api_name_n + ".value)" 472 a.julia_ctype = "Ptr{Ptr{Cint}}, Ptr{Csize_t}" 473 a.julia_pre = (api_name + " = Ref{Ptr{Cint}}()\n " + api_name_n + 474 " = Ref{Csize_t}()") 475 a.julia_arg = api_name + ", " + api_name_n 476 a.julia_post = (name + " = unsafe_wrap(Array, " + api_name + "[], " + 477 api_name_n + "[], own = true)") 478 a.fortran_type = "type(c_ptr), intent(out)" 479 a.fortran_type_post = "\n integer(c_size_t) :: " + name +"_n" 480 a.fortran_name_post = ",\n & " + name + "_n" 481 return a 482 483 484def ovectorsize(name, value=None, python_value=None, julia_value=None): 485 a = arg(name, value, python_value, julia_value, 486 "std::vector<std::size_t> &", "size_t **", True) 487 api_name = "api_" + name + "_" 488 api_name_n = api_name + "n_" 489 a.c_pre = " std::vector<std::size_t> " + api_name + ";\n" 490 a.c_arg = api_name 491 a.c_post = " vector2ptr(" + api_name + ", " + name + ", " + name + "_n);\n" 492 a.c = "size_t ** " + name + ", size_t * " + name + "_n" 493 a.cwrap_pre = "size_t *" + api_name + "; size_t " + api_name_n + ";\n" 494 a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n 495 a.cwrap_post = (name + ".assign(" + api_name + ", " + api_name + " + " + 496 api_name_n + "); " + ns + "Free(" + api_name + ");\n") 497 a.python_pre = api_name + ", " + api_name_n + " = POINTER(c_size_t)(), c_size_t()" 498 a.python_arg = "byref(" + api_name + "), byref(" + api_name_n + ")" 499 a.python_return = "_ovectorsize(" + api_name + ", " + api_name_n + ".value)" 500 a.julia_ctype = "Ptr{Ptr{Csize_t}}, Ptr{Csize_t}" 501 a.julia_pre = (api_name + " = Ref{Ptr{Csize_t}}()\n " + api_name_n + 502 " = Ref{Csize_t}()") 503 a.julia_arg = api_name + ", " + api_name_n 504 a.julia_post = (name + " = unsafe_wrap(Array, " + api_name + "[], " + 505 api_name_n + "[], own = true)") 506 a.fortran_type = "type(c_ptr), intent(out)" 507 a.fortran_type_post = "\n integer(c_size_t) :: " + name + "_n" 508 a.fortran_name_post = ",\n & " + name + "_n" 509 return a 510 511 512def ovectordouble(name, value=None, python_value=None, julia_value=None): 513 a = arg(name, value, python_value, julia_value, "std::vector<double> &", 514 "double *", True) 515 api_name = "api_" + name + "_" 516 api_name_n = api_name + "n_" 517 a.c_pre = " std::vector<double> " + api_name + ";\n" 518 a.c_arg = api_name 519 a.c_post = " vector2ptr(" + api_name + ", " + name + ", " + name + "_n);\n" 520 a.c = "double ** " + name + ", size_t * " + name + "_n" 521 a.cwrap_pre = "double *" + api_name + "; size_t " + api_name_n + ";\n" 522 a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n 523 a.cwrap_post = (name + ".assign(" + api_name + ", " + api_name + " + " + 524 api_name_n + "); " + ns + "Free(" + api_name + ");\n") 525 a.python_pre = api_name + ", " + api_name_n + " = POINTER(c_double)(), c_size_t()" 526 a.python_arg = "byref(" + api_name + "), byref(" + api_name_n + ")" 527 a.python_return = "_ovectordouble(" + api_name + ", " + api_name_n + ".value)" 528 a.julia_ctype = "Ptr{Ptr{Cdouble}}, Ptr{Csize_t}" 529 a.julia_pre = (api_name + " = Ref{Ptr{Cdouble}}()\n " + api_name_n + 530 " = Ref{Csize_t}()") 531 a.julia_arg = api_name + ", " + api_name_n 532 a.julia_post = (name + " = unsafe_wrap(Array, " + api_name + "[], " + 533 api_name_n + "[], own = true)") 534 a.fortran_type = "type(c_ptr), intent(out)" 535 a.fortran_type_post = "\n integer(c_size_t) :: " + name + "_n" 536 a.fortran_name_post = ",\n & " + name + "_n" 537 return a 538 539 540def ovectorstring(name, value=None, python_value=None, julia_value=None): 541 a = arg(name, value, python_value, julia_value, 542 "std::vector<std::string> &", "char **", True) 543 api_name = "api_" + name + "_" 544 api_name_n = api_name + "n_" 545 a.c_pre = " std::vector<std::string> " + api_name + ";\n" 546 a.c_arg = api_name 547 a.c_post = (" vectorstring2charptrptr(" + api_name + ", " + name + 548 ", " + name + "_n);\n") 549 a.c = "char *** " + name + ", size_t * " + name + "_n" 550 a.cwrap_pre = "char **" + api_name + "; size_t " + api_name_n + ";\n" 551 a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n 552 a.cwrap_post = (name + ".resize(" + api_name_n + "); " + 553 "for(size_t i = 0; i < " + api_name_n + "; ++i){ " + name + 554 "[i] = std::string(" + api_name + "[i]); " + ns + "Free(" + 555 api_name + "[i]); } " + ns + "Free(" + api_name + ");\n") 556 a.python_pre = api_name + ", " + api_name_n + " = POINTER(POINTER(c_char))(), c_size_t()" 557 a.python_arg = "byref(" + api_name + "), byref(" + api_name_n + ")" 558 a.python_return = "_ovectorstring(" + api_name + ", " + api_name_n + ".value)" 559 a.julia_ctype = "Ptr{Ptr{Ptr{Cchar}}}, Ptr{Csize_t}" 560 a.julia_pre = (api_name + " = Ref{Ptr{Ptr{Cchar}}}()\n " + api_name_n + 561 " = Ref{Csize_t}()") 562 a.julia_arg = api_name + ", " + api_name_n 563 a.julia_post = ("tmp_" + api_name + " = unsafe_wrap(Array, " + api_name + 564 "[], " + api_name_n + "[], own = true)\n " + name + 565 " = [unsafe_string(tmp_" + api_name + 566 "[i]) for i in 1:length(tmp_" + api_name + ") ]") 567 a.fortran_type = "type(c_ptr), intent(out)" 568 a.fortran_type_post = "\n integer(c_size_t) :: " + name + "_n" 569 a.fortran_name_post = ",\n & " + name + "_n" 570 return a 571 572 573def ovectorpair(name, value=None, python_value=None, julia_value=None): 574 a = arg(name, value, python_value, julia_value, ns + "::vectorpair &", 575 "int **", True) 576 api_name = "api_" + name + "_" 577 api_name_n = api_name + "n_" 578 a.c_pre = " " + ns + "::vectorpair " + api_name + ";\n" 579 a.c_arg = api_name 580 a.c_post = " vectorpair2intptr(" + api_name + ", " + name + ", " + name + "_n);\n" 581 a.c = "int ** " + name + ", size_t * " + name + "_n" 582 a.cwrap_pre = "int *" + api_name + "; size_t " + api_name_n + ";\n" 583 a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n 584 a.cwrap_post = (name + ".resize(" + api_name_n + " / 2); " + 585 "for(size_t i = 0; i < " + api_name_n + " / 2; ++i){ " + 586 name + "[i].first = " + api_name + "[i * 2 + 0]; " + name + 587 "[i].second = " + api_name + "[i * 2 + 1]; } " + ns + 588 "Free(" + api_name + ");\n") 589 a.python_pre = api_name + ", " + api_name_n + " = POINTER(c_int)(), c_size_t()" 590 a.python_arg = "byref(" + api_name + "), byref(" + api_name_n + ")" 591 a.python_return = "_ovectorpair(" + api_name + ", " + api_name_n + ".value)" 592 a.julia_ctype = "Ptr{Ptr{Cint}}, Ptr{Csize_t}" 593 a.julia_pre = (api_name + " = Ref{Ptr{Cint}}()\n " + api_name_n + 594 " = Ref{Csize_t}()") 595 a.julia_arg = api_name + ", " + api_name_n 596 a.julia_post = ("tmp_" + api_name + " = unsafe_wrap(Array, " + api_name + 597 "[], " + api_name_n + "[], own = true)\n " + name + 598 " = [ (tmp_" + api_name + "[i], tmp_" + api_name + 599 "[i+1]) " + "for i in 1:2:length(tmp_" + api_name + ") ]") 600 a.fortran_type = "type(c_ptr), intent(out)" 601 a.fortran_type_post = "\n integer(c_size_t) :: " + name + "_n" 602 a.fortran_name_post = ",\n & " + name + "_n" 603 return a 604 605 606def ovectorvectorint(name, value=None, python_value=None, julia_value=None): 607 a = arg(name, value, python_value, julia_value, 608 "std::vector<std::vector<int> > &", "int **", True) 609 api_name = "api_" + name + "_" 610 api_name_n = api_name + "n_" 611 api_name_nn = api_name + "nn_" 612 a.c_pre = " std::vector<std::vector<int> > " + api_name + ";\n" 613 a.c_arg = api_name 614 a.c_post = (" vectorvector2ptrptr(" + api_name + ", " + name + ", " + 615 name + "_n, " + name + "_nn);\n") 616 a.c = "int *** " + name + ", size_t ** " + name + "_n, size_t *" + name + "_nn" 617 a.cwrap_pre = "int **" + api_name + "; size_t *" + api_name_n + ", " + api_name_nn + ";\n" 618 a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n + ", " + "&" + api_name_nn 619 a.cwrap_post = (name + ".resize(" + api_name_nn + "); " + 620 "for(size_t i = 0; i < " + api_name_nn + "; ++i){ " + 621 name + "[i].assign(" + api_name + "[i], " + api_name + 622 "[i] + " + api_name_n + "[i]); " + ns + "Free(" + 623 api_name + "[i]); } " + ns + "Free(" + api_name + "); " + 624 ns + "Free(" + api_name_n + ");\n") 625 a.python_pre = ( 626 api_name + ", " + api_name_n + ", " + api_name_nn + 627 " = POINTER(POINTER(c_int))(), POINTER(c_size_t)(), c_size_t()") 628 a.python_arg = ("byref(" + api_name + "), byref(" + api_name_n + 629 "), byref(" + api_name_nn + ")") 630 a.python_return = ("_ovectorvectorint(" + api_name + ", " + api_name_n + 631 ", " + api_name_nn + ")") 632 a.julia_ctype = "Ptr{Ptr{Ptr{Cint}}}, Ptr{Ptr{Csize_t}}, Ptr{Csize_t}" 633 a.julia_pre = (api_name + " = Ref{Ptr{Ptr{Cint}}}()\n " + api_name_n + 634 " = Ref{Ptr{Csize_t}}()\n " + api_name_nn + 635 " = Ref{Csize_t}()") 636 a.julia_arg = api_name + ", " + api_name_n + ", " + api_name_nn 637 a.julia_post = ("tmp_" + api_name + " = unsafe_wrap(Array, " + api_name + 638 "[], " + api_name_nn + "[], own = true)\n " + "tmp_" + 639 api_name_n + " = unsafe_wrap(Array, " + api_name_n + 640 "[], " + api_name_nn + "[], own = true)\n " + name + 641 " = [ unsafe_wrap(Array, tmp_" + api_name + "[i], " + 642 "tmp_" + api_name_n + "[i], own = true) for i in 1:" + 643 api_name_nn + "[] ]") 644 a.fortran_type = "type(c_ptr), intent(out)" 645 a.fortran_type_post = ("\n type(c_ptr), intent(out) :: " + name + 646 "_n\n integer(c_size_t) :: " + name +"_nn") 647 a.fortran_name_post = ",\n & " + name + "_n,\n & " + name + "_nn" 648 return a 649 650 651def ovectorvectorsize(name, value=None, python_value=None, julia_value=None): 652 a = arg(name, value, python_value, julia_value, 653 "std::vector<std::vector<std::size_t> > &", "size_t **", True) 654 api_name = "api_" + name + "_" 655 api_name_n = api_name + "n_" 656 api_name_nn = api_name + "nn_" 657 a.c_pre = " std::vector<std::vector<std::size_t> > " + api_name + ";\n" 658 a.c_arg = api_name 659 a.c_post = (" vectorvector2ptrptr(" + api_name + ", " + name + ", " + 660 name + "_n, " + name + "_nn);\n") 661 a.c = "size_t *** " + name + ", size_t ** " + name + "_n, size_t *" + name + "_nn" 662 a.cwrap_pre = "size_t **" + api_name + "; size_t *" + api_name_n + ", " + api_name_nn + ";\n" 663 a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n + ", " + "&" + api_name_nn 664 a.cwrap_post = (name + ".resize(" + api_name_nn + "); " + 665 "for(size_t i = 0; i < " + api_name_nn + "; ++i){ " + 666 name + "[i].assign(" + api_name + "[i], " + api_name + 667 "[i] + " + api_name_n + "[i]); " + ns + "Free(" + 668 api_name + "[i]); } " + ns + "Free(" + api_name + "); " + 669 ns + "Free(" + api_name_n + ");\n") 670 a.python_pre = ( 671 api_name + ", " + api_name_n + ", " + api_name_nn + 672 " = POINTER(POINTER(c_size_t))(), POINTER(c_size_t)(), c_size_t()") 673 a.python_arg = ("byref(" + api_name + "), byref(" + api_name_n + 674 "), byref(" + api_name_nn + ")") 675 a.python_return = ("_ovectorvectorsize(" + api_name + ", " + api_name_n + 676 ", " + api_name_nn + ")") 677 a.julia_ctype = "Ptr{Ptr{Ptr{Csize_t}}}, Ptr{Ptr{Csize_t}}, Ptr{Csize_t}" 678 a.julia_pre = (api_name + " = Ref{Ptr{Ptr{Csize_t}}}()\n " + 679 api_name_n + " = Ref{Ptr{Csize_t}}()\n " + api_name_nn + 680 " = Ref{Csize_t}()") 681 a.julia_arg = api_name + ", " + api_name_n + ", " + api_name_nn 682 a.julia_post = ("tmp_" + api_name + " = unsafe_wrap(Array, " + api_name + 683 "[], " + api_name_nn + "[], own = true)\n " + "tmp_" + 684 api_name_n + " = unsafe_wrap(Array, " + api_name_n + 685 "[], " + api_name_nn + "[], own = true)\n " + name + 686 " = [ unsafe_wrap(Array, tmp_" + api_name + "[i], " + 687 "tmp_" + api_name_n + "[i], own = true) for i in 1:" + 688 api_name_nn + "[] ]") 689 a.fortran_type = "type (c_ptr), intent(out)" 690 a.fortran_type_post = ("\n type(c_ptr), intent(out) :: " + name + 691 "_n\n integer(c_size_t) :: " + name +"_nn") 692 a.fortran_name_post = ",\n & " + name + "_n,\n & " + name + "_nn" 693 return a 694 695 696def ovectorvectordouble(name, value=None, python_value=None, julia_value=None): 697 a = arg(name, value, python_value, julia_value, 698 "std::vector<std::vector<double> > &", "double **", True) 699 api_name = "api_" + name + "_" 700 api_name_n = api_name + "n_" 701 api_name_nn = api_name + "nn_" 702 a.c_pre = " std::vector<std::vector<double> > " + api_name + ";\n" 703 a.c_arg = api_name 704 a.c_post = (" vectorvector2ptrptr(" + api_name + ", " + name + ", " + 705 name + "_n, " + name + "_nn);\n") 706 a.c = "double *** " + name + ", size_t ** " + name + "_n, size_t *" + name + "_nn" 707 a.cwrap_pre = ("double **" + api_name + "; size_t *" + api_name_n + ", " + 708 api_name_nn + ";\n") 709 a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n + ", " + "&" + api_name_nn 710 a.cwrap_post = (name + ".resize(" + api_name_nn + "); " + 711 "for(size_t i = 0; i < " + api_name_nn + "; ++i){ " + 712 name + "[i].assign(" + api_name + "[i], " + api_name + 713 "[i] + " + api_name_n + "[i]); " + ns + "Free(" + 714 api_name + "[i]); } " + ns + "Free(" + api_name + "); " + 715 ns + "Free(" + api_name_n + ");\n") 716 a.python_pre = ( 717 api_name + ", " + api_name_n + ", " + api_name_nn + 718 " = POINTER(POINTER(c_double))(), POINTER(c_size_t)(), c_size_t()") 719 a.python_arg = ("byref(" + api_name + "), byref(" + api_name_n + 720 "), byref(" + api_name_nn + ")") 721 a.python_return = ("_ovectorvectordouble(" + api_name + ", " + api_name_n + 722 ", " + api_name_nn + ")") 723 a.julia_ctype = "Ptr{Ptr{Ptr{Cdouble}}}, Ptr{Ptr{Csize_t}}, Ptr{Csize_t}" 724 a.julia_pre = (api_name + " = Ref{Ptr{Ptr{Cdouble}}}()\n " + 725 api_name_n + " = Ref{Ptr{Csize_t}}()\n " + api_name_nn + 726 " = Ref{Csize_t}()") 727 a.julia_arg = api_name + ", " + api_name_n + ", " + api_name_nn 728 a.julia_post = ("tmp_" + api_name + " = unsafe_wrap(Array, " + api_name + 729 "[], " + api_name_nn + "[], own = true)\n " + "tmp_" + 730 api_name_n + " = unsafe_wrap(Array, " + api_name_n + 731 "[], " + api_name_nn + "[], own = true)\n " + name + 732 " = [ unsafe_wrap(Array, tmp_" + api_name + "[i], " + 733 "tmp_" + api_name_n + "[i], own = true) for i in 1:" + 734 api_name_nn + "[] ]") 735 a.fortran_type = "type (c_ptr), intent(out)" 736 a.fortran_type_post = ("\n type(c_ptr), intent(out) :: " + name + 737 "_n\n integer (c_size_t) :: " + name + "_nn") 738 a.fortran_name_post = ",\n & " + name + "_n,\n & " + name + "_nn" 739 return a 740 741 742def ovectorvectorpair(name, value=None, python_value=None, julia_value=None): 743 a = arg(name, value, python_value, julia_value, 744 "std::vector<" + ns + "::vectorpair> &", "int **", True) 745 api_name = "api_" + name + "_" 746 api_name_n = api_name + "n_" 747 api_name_nn = api_name + "nn_" 748 a.c_pre = " std::vector<" + ns + "::vectorpair >" + api_name + ";\n" 749 a.c_arg = api_name 750 a.c_post = (" vectorvectorpair2intptrptr(" + api_name + ", " + name + 751 ", " + name + "_n, " + name + "_nn);\n") 752 a.c = "int *** " + name + ", size_t ** " + name + "_n, size_t *" + name + "_nn" 753 a.cwrap_pre = "int **" + api_name + "; size_t *" + api_name_n + ", " + api_name_nn + ";\n" 754 a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n + ", " + "&" + api_name_nn 755 a.cwrap_post = (name + ".resize(" + api_name_nn + "); " + 756 "for(size_t i = 0; i < " + api_name_nn + "; ++i){ " + 757 name + "[i].resize(" + api_name_n + "[i] / 2); " + 758 "for(size_t j = 0; j < " + api_name_n + "[i] / 2; ++j){ " + 759 name + "[i][j].first = " + api_name + "[i][j * 2 + 0]; " + 760 name + "[i][j].second = " + api_name + 761 "[i][j * 2 + 1]; } " + ns + "Free(" + api_name + 762 "[i]); } " + ns + "Free(" + api_name + "); " + ns + 763 "Free(" + api_name_n + ");\n") 764 a.python_pre = ( 765 api_name + ", " + api_name_n + ", " + api_name_nn + 766 " = POINTER(POINTER(c_int))(), POINTER(c_size_t)(), c_size_t()") 767 a.python_arg = ("byref(" + api_name + "), byref(" + api_name_n + 768 "), byref(" + api_name_nn + ")") 769 a.python_return = ("_ovectorvectorpair(" + api_name + ", " + api_name_n + 770 ", " + api_name_nn + ")") 771 a.julia_ctype = "Ptr{Ptr{Ptr{Cint}}}, Ptr{Ptr{Csize_t}}, Ptr{Csize_t}" 772 a.julia_pre = (api_name + " = Ref{Ptr{Ptr{Cint}}}()\n " + api_name_n + 773 " = Ref{Ptr{Csize_t}}()\n " + api_name_nn + 774 " = Ref{Csize_t}()") 775 a.julia_arg = api_name + ", " + api_name_n + ", " + api_name_nn 776 a.julia_post = ( 777 "tmp_" + api_name + " = unsafe_wrap(Array, " + api_name + "[], " + 778 api_name_nn + "[], own = true)\n " + "tmp_" + api_name_n + 779 " = unsafe_wrap(Array, " + api_name_n + "[], " + api_name_nn + 780 "[], own = true)\n " + name + " = Vector{Tuple{Cint,Cint}}[]\n " + 781 "resize!(" + name + ", " + api_name_nn + "[])\n " + "for i in 1:" + 782 api_name_nn + "[]\n " + " tmp = unsafe_wrap(Array, tmp_" + 783 api_name + "[i], tmp_" + api_name_n + "[i], own = true)\n " + " " + 784 name + "[i] = [(tmp[i], tmp[i+1]) for i in 1:2:length(tmp)]\n " + 785 "end") 786 a.fortran_type = "type (C_PTR), intent(out)" 787 a.fortran_type_post = ("\n type(c_ptr), intent(out) :: " + name + 788 "_n\n integer (C_SIZE_T) ::" + name +"_nn") 789 a.fortran_name_post = ",\n & " + name + "_n,\n & " + name + "_nn" 790 return a 791 792 793# special types 794 795 796def iargcargv(): 797 a = arg("", None, None, None, "", "", False) 798 a.cpp = "int argc = 0, char ** argv = 0" 799 a.c_arg = "argc, argv" 800 a.c = "int argc, char ** argv" 801 a.c_pre = "" 802 a.c_post = "" 803 a.cwrap_arg = "argc, argv" 804 a.name = "argv" 805 a.python_value = "[]" 806 a.julia_value = "Vector{String}()" 807 a.python_arg = "api_argc_, api_argv_" 808 a.python_pre = "api_argc_, api_argv_ = _iargcargv(argv)" 809 a.julia_ctype = "Cint, Ptr{Ptr{Cchar}}" 810 a.julia_arg = "length(argv), argv" 811 a.texi = "(argc = 0)}, @code{argv = []" 812 a.fortran_name_pre = "argc,\n & " 813 a.fortran_type = "integer (C_INT), value :: argc\n type (C_PTR)" 814 a.fortran_type_post = "(*)" 815 return a 816 817 818def isizefun(name): 819 a = arg(name, None, None, None, "", "", False) 820 a.cpp = "std::function<double(int, int, double, double, double, double)> " + name 821 a.c_arg = ("std::bind(" + name + ", std::placeholders::_1, " + 822 "std::placeholders::_2, std::placeholders::_3, " + 823 "std::placeholders::_4, std::placeholders::_5, " + 824 "std::placeholders::_6, " + name + "_data)") 825 a.c = ("double (*" + name + ")" + 826 "(int dim, int tag, double x, double y, double z, double lc, void * data), " + 827 "void * " + name + "_data") 828 a.cwrap_pre = "struct " + name + """_caller_ { 829 static double call(int dim, int tag, double x, double y, double z, double lc, void * callbackp_) { 830 return (*static_cast<std::function<double(int, int, double, double, double, double)>*> (callbackp_))(dim, tag, x, y, z, lc); 831 } 832 }; 833 // FIXME memory leak 834 auto *""" + name + "_ptr_ = new std::function<double(int, int, double, double, double, double)>(" + name + """); 835""" 836 a.cwrap_arg = "&" + name + "_caller_::call, " + name + "_ptr_" 837 a.python_pre = ( 838 "global api_" + name + "_type_\n" + " api_" + name + 839 "_type_ = " + 840 "CFUNCTYPE(c_double, c_int, c_int, c_double, c_double, c_double, c_double, c_void_p)\n" 841 + " global api_" + name + "_\n" + " api_" + 842 name + "_ = api_" + name + "_type_(lambda dim, tag, x, y, z, lc, _ : " + 843 name + "(dim, tag, x, y, z, lc))") 844 a.python_arg = "api_" + name + "_, None" 845 a.julia_pre = ( 846 "api_" + name + "__(dim, tag, x, y, z, lc, data) = " + name + 847 "(dim, tag, x, y, z, lc)\n " + "api_" + name + "_ = @cfunction($api_" + 848 name + "__" + 849 ", Cdouble, (Cint, Cint, Cdouble, Cdouble, Cdouble, Cdouble, Ptr{Cvoid}))") 850 a.julia_arg = "api_" + name + "_, C_NULL" 851 a.julia_ctype = "Ptr{Cvoid}, Ptr{Cvoid}" 852 a.fortran_type = "type (C_FUNPTR)" 853 a.fortran_type_post = " ! to do " 854 return a 855 856 857class Module: 858 def __init__(self, name, doc): 859 self.name = name 860 self.doc = doc 861 self.fs = [] 862 self.submodules = [] 863 864 def add(self, name, doc, rtype, *args): 865 self.fs.append((rtype, name, args, doc, [])) 866 867 def add_special(self, name, doc, special, rtype, *args): 868 self.fs.append((rtype, name, args, doc, special)) 869 870 def add_module(self, name, doc): 871 module = Module(name, doc) 872 self.submodules.append(module) 873 return module 874 875 876cpp_header = """// {0} 877// 878// See the LICENSE.txt file in the {3} root directory for license information. 879// Please report all issues on {1} 880 881#ifndef {2}_H 882#define {2}_H 883 884// This file defines the {3} C++ API (v{4}.{5}.{6}). 885// 886// Do not edit it directly: it is automatically generated by `api/gen.py'. 887// 888// By design, the {3} C++ API is purely functional, and only uses elementary 889// types from the C++ standard library. See `tutorial/c++' and `demos/api' for 890// examples. 891 892#include <cmath> 893#include <vector> 894#include <string> 895#include <utility> 896#include <functional> 897 898#define {2}_API_VERSION "{4}.{5}.{6}" 899#define {2}_API_VERSION_MAJOR {4} 900#define {2}_API_VERSION_MINOR {5} 901#define {2}_API_VERSION_PATCH {6} 902 903#if defined({2}_DLL) 904#if defined({2}_DLL_EXPORT) 905#define {2}_API __declspec(dllexport) 906#else 907#define {2}_API __declspec(dllimport) 908#endif 909#else 910#define {2}_API 911#endif 912 913#ifndef M_PI 914#define M_PI (3.14159265358979323846) 915#endif 916 917namespace {7} {{ 918 919 // A geometrical entity in the {3} API is represented by two integers: its 920 // dimension (dim = 0, 1, 2 or 3) and its tag (its unique, strictly positive 921 // identifier). When dealing with multiple geometrical entities of possibly 922 // different dimensions, the entities are packed as a vector of (dim, tag) 923 // integer pairs. 924 typedef std::vector<std::pair<int, int> > vectorpair; 925 926}} 927 928""" 929 930cpp_footer = """#endif 931""" 932 933c_header = """/* 934 * {0} 935 * 936 * See the LICENSE.txt file in the {3} root directory for license information. 937 * Please report all issues on {1} 938 */ 939 940#ifndef {2}C_H 941#define {2}C_H 942 943/* 944 * This file defines the {3} C API (v{4}.{5}.{6}). 945 * 946 * Do not edit it directly: it is automatically generated by `api/gen.py'. 947 * 948 * By design, the {3} C API is purely functional, and only uses elementary 949 * C types. See `tutorial/c' and `demos/api' for examples. 950 */ 951 952#include <stddef.h> 953 954#define {2}_API_VERSION "{4}.{5}.{6}" 955#define {2}_API_VERSION_MAJOR {4} 956#define {2}_API_VERSION_MINOR {5} 957#define {2}_API_VERSION_PATCH {6} 958 959#if defined({2}_DLL) 960#if defined({2}_DLL_EXPORT) 961#define {2}_API __declspec(dllexport) 962#else 963#define {2}_API __declspec(dllimport) 964#endif 965#else 966#define {2}_API 967#endif 968 969{2}_API void {7}Free(void *p); 970{2}_API void *{7}Malloc(size_t n); 971""" 972 973c_footer = """ 974#endif 975""" 976 977c_cpp_header = """// {0} 978// 979// See the LICENSE.txt file in the {4} root directory for license information. 980// Please report all issues on {1} 981 982#include <string.h> 983#include <stdlib.h> 984#include "{2}.h" 985 986extern \"C\" {{ 987 #include "{2}c.h" 988}} 989 990{3}_API void *{2}Malloc(size_t n) 991{{ 992 return malloc(n); 993}} 994 995{3}_API void {2}Free(void *p) 996{{ 997 if(p) free(p); 998}} 999""" 1000 1001c_cpp_utils = """ 1002void vectorvectorpair2intptrptr(const std::vector<{0}::vectorpair > &v, int ***p, size_t **size, size_t *sizeSize) 1003{{ 1004 *p = (int**){0}Malloc(sizeof(int*) * v.size()); 1005 *size = (size_t*){0}Malloc(sizeof(size_t) * v.size()); 1006 for(size_t i = 0; i < v.size(); ++i) 1007 vectorpair2intptr(v[i], &(*p)[i], &((*size)[i])); 1008 *sizeSize = v.size(); 1009}} 1010""" 1011 1012cwrap_header = """// {0} 1013// 1014// See the LICENSE.txt file in the {3} root directory for license information. 1015// Please report all issues on {1} 1016 1017#ifndef {2}_H 1018#define {2}_H 1019 1020// This file redefines the {3} C++ API in terms of the C API (v{4}.{5}.{6}). 1021// 1022// This is provided as a convenience for users of the binary {3} SDK whose C++ 1023// compiler ABI is not compatible with the ABI of the C++ compiler used to create 1024// the SDK (and who can thus not directly use the C++ API defined in `{7}.h'). 1025// 1026// To use this header file in your C++ code, simply rename it as `{7}.h'. 1027// 1028// Note that using this header file will lead to (slightly) reduced performance 1029// compared to using the native {3} C++ API from the original `{7}.h', as it 1030// entails additional data copies between this C++ wrapper, the C API and the 1031// native C++ code. 1032// 1033// Do not edit this file directly: it is automatically generated by `api/gen.py'. 1034 1035#include <cmath> 1036#include <vector> 1037#include <string> 1038#include <utility> 1039#include <functional> 1040 1041#ifndef M_PI 1042#define M_PI (3.14159265358979323846) 1043#endif 1044 1045extern \"C\" {{ 1046 #include "{7}c.h" 1047}} 1048 1049namespace {7} {{ 1050 1051 // A geometrical entity in the {3} API is represented by two integers: its 1052 // dimension (dim = 0, 1, 2 or 3) and its tag (its unique, strictly positive 1053 // identifier). When dealing with multiple geometrical entities of possibly 1054 // different dimensions, the entities are packed as a vector of (dim, tag) 1055 // integer pairs. 1056 typedef std::vector<std::pair<int, int> > vectorpair; 1057 1058}} 1059 1060""" 1061 1062cwrap_utils = """ 1063template<typename t> 1064{1}void vector2ptr(const std::vector<t> &v, t **p, size_t *size) 1065{{ 1066 *p = (t*){0}Malloc(sizeof(t) * v.size()); 1067 for(size_t i = 0; i < v.size(); ++i){{ 1068 (*p)[i] = v[i]; 1069 }} 1070 *size = v.size(); 1071}} 1072 1073{1}void vectorpair2intptr(const {0}::vectorpair &v, int **p, size_t *size) 1074{{ 1075 *p = (int*){0}Malloc(sizeof(int) * v.size() * 2); 1076 for(size_t i = 0; i < v.size(); ++i){{ 1077 (*p)[i * 2 + 0] = v[i].first; 1078 (*p)[i * 2 + 1] = v[i].second; 1079 }} 1080 *size = v.size() * 2; 1081}} 1082 1083{1}void vectorstring2charptrptr(const std::vector<std::string> &v, char ***p, size_t *size) 1084{{ 1085 *p = (char**){0}Malloc(sizeof(char*) * v.size()); 1086 for(size_t i = 0; i < v.size(); ++i){{ 1087 (*p)[i] = (char*){0}Malloc(sizeof(char) * (v[i].size() + 1)); 1088 for(size_t j = 0; j < v[i].size(); j++) (*p)[i][j] = v[i][j]; 1089 (*p)[i][v[i].size()] = '\\0'; 1090 }} 1091 *size = v.size(); 1092}} 1093 1094template<typename t> 1095{1}void vectorvector2ptrptr(const std::vector<std::vector<t> > &v, t ***p, size_t **size, size_t *sizeSize) 1096{{ 1097 *p = (t**){0}Malloc(sizeof(t*) * v.size()); 1098 *size = (size_t*){0}Malloc(sizeof(size_t) * v.size()); 1099 for(size_t i = 0; i < v.size(); ++i) 1100 vector2ptr(v[i], &((*p)[i]), &((*size)[i])); 1101 *sizeSize = v.size(); 1102}} 1103""" 1104 1105cwrap_footer = """#endif 1106""" 1107 1108python_header = """# {0} 1109# 1110# See the LICENSE.txt file in the {2} root directory for license information. 1111# Please report all issues on {1} 1112 1113# This file defines the {2} Python API (v{3}.{4}.{5}). 1114# 1115# Do not edit it directly: it is automatically generated by `api/gen.py'. 1116# 1117# By design, the {2} Python API is purely functional, and only uses elementary 1118# Python types (as well as `numpy' arrays if `numpy' is available). See 1119# `tutorial/python' and `demos/api' for examples. 1120 1121from ctypes import * 1122from ctypes.util import find_library 1123import signal 1124import os 1125import platform 1126from math import pi 1127 1128{6}_API_VERSION = "{3}.{4}.{5}" 1129{6}_API_VERSION_MAJOR = {3} 1130{6}_API_VERSION_MINOR = {4} 1131{6}_API_VERSION_PATCH = {5} 1132 1133__version__ = {6}_API_VERSION 1134 1135oldsig = signal.signal(signal.SIGINT, signal.SIG_DFL) 1136moduledir = os.path.dirname(os.path.realpath(__file__)) 1137if platform.system() == "Windows": 1138 libname = "{7}-{3}.{4}.dll" 1139 libdir = os.path.dirname(moduledir) 1140elif platform.system() == "Darwin": 1141 libname = "lib{7}.{3}.{4}.dylib" 1142 libdir = os.path.dirname(os.path.dirname(moduledir)) 1143else: 1144 libname = "lib{7}.so.{3}.{4}" 1145 libdir = os.path.dirname(os.path.dirname(moduledir)) 1146 1147libpath = os.path.join(libdir, libname) 1148if not os.path.exists(libpath): 1149 libpath = os.path.join(libdir, "Lib", libname) 1150if not os.path.exists(libpath): 1151 libpath = os.path.join(moduledir, libname) 1152if not os.path.exists(libpath): 1153 if platform.system() == "Windows": 1154 libpath = find_library("{7}-{3}.{4}") 1155 else: 1156 libpath = find_library("{7}") 1157 1158lib = CDLL(libpath) 1159 1160try_numpy = True # set this to False to never use numpy 1161 1162use_numpy = False 1163if try_numpy: 1164 try: 1165 import numpy 1166 try: 1167 from weakref import finalize as weakreffinalize 1168 except: 1169 from backports.weakref import finalize as weakreffinalize 1170 use_numpy = True 1171 except: 1172 pass 1173 1174# Utility functions, not part of the Gmsh Python API 1175 1176def _ostring(s): 1177 sp = s.value.decode("utf-8") 1178 lib.{7}Free(s) 1179 return sp 1180 1181def _ovectorpair(ptr, size): 1182 v = list((ptr[i * 2], ptr[i * 2 + 1]) for i in range(size//2)) 1183 lib.{7}Free(ptr) 1184 return v 1185 1186def _ovectorint(ptr, size): 1187 if use_numpy: 1188 if size == 0 : 1189 lib.{7}Free(ptr) 1190 return numpy.ndarray((0,),numpy.int32) 1191 v = numpy.ctypeslib.as_array(ptr, (size, )) 1192 weakreffinalize(v, lib.{7}Free, ptr) 1193 else: 1194 v = list(ptr[i] for i in range(size)) 1195 lib.{7}Free(ptr) 1196 return v 1197 1198def _ovectorsize(ptr, size): 1199 if use_numpy: 1200 if size == 0 : 1201 lib.{7}Free(ptr) 1202 return numpy.ndarray((0,),numpy.uintp) 1203 v = numpy.ctypeslib.as_array(ptr, (size, )) 1204 weakreffinalize(v, lib.{7}Free, ptr) 1205 else: 1206 v = list(ptr[i] for i in range(size)) 1207 lib.{7}Free(ptr) 1208 return v 1209 1210def _ovectordouble(ptr, size): 1211 if use_numpy: 1212 if size == 0 : 1213 lib.{7}Free(ptr) 1214 return numpy.ndarray((0,),numpy.float64) 1215 v = numpy.ctypeslib.as_array(ptr, (size, )) 1216 weakreffinalize(v, lib.{7}Free, ptr) 1217 else: 1218 v = list(ptr[i] for i in range(size)) 1219 lib.{7}Free(ptr) 1220 return v 1221 1222def _ovectorstring(ptr, size): 1223 v = list(_ostring(cast(ptr[i], c_char_p)) for i in range(size)) 1224 lib.{7}Free(ptr) 1225 return v 1226 1227def _ovectorvectorint(ptr, size, n): 1228 v = [_ovectorint(pointer(ptr[i].contents), size[i]) for i in range(n.value)] 1229 lib.{7}Free(size) 1230 lib.{7}Free(ptr) 1231 return v 1232 1233def _ovectorvectorsize(ptr, size, n): 1234 v = [_ovectorsize(pointer(ptr[i].contents), size[i]) for i in range(n.value)] 1235 lib.{7}Free(size) 1236 lib.{7}Free(ptr) 1237 return v 1238 1239def _ovectorvectordouble(ptr, size, n): 1240 v = [_ovectordouble(pointer(ptr[i].contents), size[i]) for i in range(n.value)] 1241 lib.{7}Free(size) 1242 lib.{7}Free(ptr) 1243 return v 1244 1245def _ovectorvectorpair(ptr, size, n): 1246 v = [_ovectorpair(pointer(ptr[i].contents), size[i]) for i in range(n.value)] 1247 lib.{7}Free(size) 1248 lib.{7}Free(ptr) 1249 return v 1250 1251def _ivectorint(o): 1252 if use_numpy: 1253 array = numpy.ascontiguousarray(o, numpy.int32) 1254 if(len(o) and array.ndim != 1): 1255 raise Exception("Invalid data for input vector of integers") 1256 ct = array.ctypes 1257 ct.array = array 1258 return ct, c_size_t(len(o)) 1259 else: 1260 return (c_int * len(o))(*o), c_size_t(len(o)) 1261 1262def _ivectorsize(o): 1263 if use_numpy: 1264 array = numpy.ascontiguousarray(o, numpy.uintp) 1265 if(len(o) and array.ndim != 1): 1266 raise Exception("Invalid data for input vector of sizes") 1267 ct = array.ctypes 1268 ct.array = array 1269 return ct, c_size_t(len(o)) 1270 else: 1271 return (c_size_t * len(o))(*o), c_size_t(len(o)) 1272 1273def _ivectordouble(o): 1274 if use_numpy: 1275 array = numpy.ascontiguousarray(o, numpy.float64) 1276 if(len(o) and array.ndim != 1): 1277 raise Exception("Invalid data for input vector of doubles") 1278 ct = array.ctypes 1279 ct.array = array 1280 return ct, c_size_t(len(o)) 1281 else: 1282 return (c_double * len(o))(*o), c_size_t(len(o)) 1283 1284def _ivectorpair(o): 1285 if use_numpy: 1286 array = numpy.ascontiguousarray(o, numpy.int32) 1287 if(len(o) and (array.ndim != 2 or array.shape[1] != 2)): 1288 raise Exception("Invalid data for input vector of pairs") 1289 ct = array.ctypes 1290 ct.array = array 1291 return ct, c_size_t(len(o) * 2) 1292 else: 1293 if(len(o) and len(o[0]) != 2): 1294 raise Exception("Invalid data for input vector of pairs") 1295 return ((c_int * 2) * len(o))(*o), c_size_t(len(o) * 2) 1296 1297def _ivectorstring(o): 1298 return (c_char_p * len(o))(*(s.encode() for s in o)), c_size_t(len(o)) 1299 1300def _ivectorvectorint(os): 1301 n = len(os) 1302 parrays = [_ivectorint(o) for o in os] 1303 sizes = (c_size_t * n)(*(a[1] for a in parrays)) 1304 arrays = (POINTER(c_int) * n)(*(cast(a[0], POINTER(c_int)) for a in parrays)) 1305 arrays.ref = [a[0] for a in parrays] 1306 size = c_size_t(n) 1307 return arrays, sizes, size 1308 1309def _ivectorvectorsize(os): 1310 n = len(os) 1311 parrays = [_ivectorsize(o) for o in os] 1312 sizes = (c_size_t * n)(*(a[1] for a in parrays)) 1313 arrays = (POINTER(c_size_t) * n)(*(cast(a[0], POINTER(c_size_t)) for a in parrays)) 1314 arrays.ref = [a[0] for a in parrays] 1315 size = c_size_t(n) 1316 return arrays, sizes, size 1317 1318def _ivectorvectordouble(os): 1319 n = len(os) 1320 parrays = [_ivectordouble(o) for o in os] 1321 sizes = (c_size_t * n)(*(a[1] for a in parrays)) 1322 arrays = (POINTER(c_double) * n)(*(cast(a[0], POINTER(c_double)) for a in parrays)) 1323 arrays.ref = [a[0] for a in parrays] 1324 size = c_size_t(n) 1325 return arrays, sizes, size 1326 1327def _iargcargv(o): 1328 return c_int(len(o)), (c_char_p * len(o))(*(s.encode() for s in o)) 1329 1330# Gmsh Python API begins here 1331""" 1332 1333julia_header = """# {0} 1334# 1335# See the LICENSE.txt file in the {2} root directory for license information. 1336# Please report all issues on {1} 1337 1338# This file defines the {2} Julia API (v{3}.{4}.{5}). 1339# 1340# Do not edit it directly: it is automatically generated by `api/gen.py'. 1341# 1342# By design, the {2} Julia API is purely functional, and only uses elementary 1343# Julia types. See `tutorial/julia' and `demos/api' for examples. 1344""" 1345 1346 1347fortran_header = """c 1348c {0} 1349c 1350c See the LICENSE.txt file in the {3} root directory for license information. 1351c Please report all issues on {1} 1352c 1353 1354!DEC$ IF DEFINED ({2}F_H) 1355!DEC$ ELSE 1356!DEC$ DEFINE {2}F_H 1357 1358c 1359c This file defines the {3} Fortran API (v{4}.{5}.{6}). 1360c 1361c Do not edit it directly: it is automatically generated by `api/gen.py'. 1362c 1363c By design, the {3} Fortran API is purely functional, and only uses elementary 1364c Fortran types. See `tutorial/fortran' and `demos/api' for examples. 1365c 1366 1367!DEC$ DEFINE {2}_API_VERSION_MAJOR = {4} 1368!DEC$ DEFINE {2}_API_VERSION_MINOR = {5} 1369!DEC$ DEFINE {2}_API_VERSION_PATCH = {6} 1370 1371 module gmsh_fortran 1372 1373 use, intrinsic :: iso_c_binding 1374 1375 character(len = 5), parameter :: {2}_API_VERSION = "{4}.{5}.{6}" 1376 real(c_double), parameter::M_PI = 3.14159265358979323846d0 1377 1378 interface 1379""" 1380 1381fortran_footer = """ 1382 end interface 1383 end module gmsh_fortran 1384 1385!DEC$ ENDIF 1386""" 1387 1388 1389def capi(s): 1390 return s[:1].upper() + s[1:] 1391 1392 1393class API: 1394 def __init__( 1395 self, 1396 version_major, 1397 version_minor, 1398 version_patch, 1399 namespace = "gmsh", 1400 code = "Gmsh", 1401 copyright = "Gmsh - Copyright (C) 1997-2021 C. Geuzaine, J.-F. Remacle", 1402 issues = "https://gitlab.onelab.info/gmsh/gmsh/issues."): 1403 self.version_major = version_major 1404 self.version_minor = version_minor 1405 self.version_patch = version_patch 1406 global ns 1407 ns = namespace 1408 self.code = code 1409 self.copyright = copyright 1410 self.issues = issues 1411 self.modules = [] 1412 self.api_lineno = {'cpp': {}, 'c': {}, 'py': {}, 'jl': {}, 'f': {}} 1413 1414 def add_module(self, name, doc): 1415 module = Module(name, doc) 1416 self.modules.append(module) 1417 return module 1418 1419 def fwrite(self, f, s): 1420 self.current_lineno += s.count('\n') 1421 f.write(s) 1422 1423 def flog(self, lang, fname): 1424 self.api_lineno[lang][fname] = self.current_lineno 1425 1426 def write_cpp(self): 1427 def write_module(module, indent, cpp_mpath): 1428 cpp_mpath += module.name + "::" 1429 self.fwrite( 1430 f, indent + "namespace " + module.name + " { // " + 1431 capi(module.doc) + "\n\n") 1432 indent += " " 1433 for rtype, name, args, doc, special in module.fs: 1434 rt = rtype.rcpp_type if rtype else "void" 1435 self.fwrite( 1436 f, 1437 indent + "// " + cpp_mpath + name + "\n" + indent + "//\n") 1438 self.fwrite( 1439 f, indent + "// " + ("\n" + indent + "// ").join( 1440 textwrap.wrap(doc, 80 - len(indent))) + "\n") 1441 fnameapi = indent + ns.upper( 1442 ) + "_API " + rt + " " + name + "(" 1443 self.flog('cpp', cpp_mpath.replace('::', '/') + name) 1444 self.fwrite(f, fnameapi) 1445 if args: 1446 self.fwrite(f, (",\n" + ' ' * len(fnameapi)).join( 1447 a.cpp for a in args)) 1448 self.fwrite(f, ");\n\n") 1449 for m in module.submodules: 1450 write_module(m, indent, cpp_mpath) 1451 self.fwrite(f, 1452 indent[:-2] + "} // namespace " + module.name + "\n\n") 1453 1454 self.current_lineno = 1 1455 with open(ns + ".h", "w") as f: 1456 self.fwrite( 1457 f, 1458 cpp_header.format(self.copyright, self.issues, ns.upper(), 1459 self.code, self.version_major, 1460 self.version_minor, self.version_patch, ns)) 1461 for m in self.modules: 1462 write_module(m, "", "") 1463 self.fwrite(f, cpp_footer) 1464 1465 def write_c(self): 1466 def write_module(module, c_namespace, cpp_namespace, indent): 1467 cpp_namespace += module.name + "::" 1468 if c_namespace: 1469 c_namespace += module.name[0].upper() + module.name[1:] 1470 else: 1471 c_namespace = module.name 1472 fcwrap.write(indent + "namespace " + module.name + " { // " + 1473 capi(module.doc) + "\n\n") 1474 indent += " " 1475 for rtype, name, args, doc, special in module.fs: 1476 # *c.h 1477 fname = c_namespace + name[0].upper() + name[1:] 1478 self.fwrite( 1479 f, 1480 "\n/* " + "\n * ".join(textwrap.wrap(doc, 75)) + " */\n") 1481 fnameapi = ns.upper() + "_API " + (rtype.rc_type if rtype else 1482 "void") + " " + fname + "(" 1483 self.flog('c', cpp_namespace.replace('::', '/') + name) 1484 self.fwrite( 1485 f, fnameapi + (",\n" + ' ' * len(fnameapi)).join( 1486 list((a.c for a in args + (oint("ierr"), )))) + ");\n") 1487 1488 if "rawc" not in special: 1489 # *c.cpp 1490 fc.write(ns.upper() + "_API " + 1491 (rtype.rc_type if rtype else "void")) 1492 fc.write( 1493 " " + fname + "(" + 1494 ", ".join(list((a.c for a in args + 1495 (oint("ierr"), )))) + ")\n{\n") 1496 if rtype: 1497 fc.write(" " + rtype.rc_type + " result_api_ = 0;\n") 1498 fc.write(" if(ierr) *ierr = 0;\n") 1499 fc.write(" try {\n") 1500 fc.write("".join((a.c_pre for a in args))) 1501 fc.write(" ") 1502 if rtype: 1503 fc.write("result_api_ = ") 1504 fc.write(cpp_namespace + name + "(" + 1505 ", ".join(list((a.c_arg for a in args))) + ");\n") 1506 fc.write("".join((a.c_post for a in args))) 1507 fc.write(" }\n catch(...){\n " + 1508 "if(ierr) *ierr = 1;\n }\n") 1509 if rtype: 1510 fc.write(" return result_api_;\n") 1511 fc.write("}\n\n") 1512 # *.h_cwrap 1513 fcwrap.write(indent + "// " + 1514 ("\n" + indent + 1515 "// ").join(textwrap.wrap(doc, 80 - 1516 len(indent))) + "\n") 1517 rt = rtype.rcpp_type if rtype else "void" 1518 fnameapi = indent + "inline " + rt + " " + name + "(" 1519 fcwrap.write(fnameapi) 1520 if args: 1521 fcwrap.write( 1522 (",\n" + ' ' * len(fnameapi)).join(a.cpp 1523 for a in args)) 1524 fcwrap.write(")\n" + indent + "{\n" + indent + 1525 " int ierr = 0;\n") 1526 for a in args: 1527 if a.cwrap_pre: 1528 fcwrap.write(indent + " " + a.cwrap_pre) 1529 fcwrap.write(indent + " ") 1530 if rtype: 1531 fcwrap.write(rt + " result_api_ = ") 1532 fcwrap.write(fname + "(" + ", ".join((a.cwrap_arg 1533 for a in args))) 1534 if args: 1535 fcwrap.write(", &ierr);\n") 1536 else: 1537 fcwrap.write("&ierr);\n") 1538 if name == 'getLastError': # special case for getLastError() function 1539 fcwrap.write( 1540 indent + " " + 1541 'if(ierr) throw "Could not get last error";\n') 1542 else: 1543 fcwrap.write(indent + " " + 1544 "if(ierr) throwLastError();\n") 1545 for a in args: 1546 if a.cwrap_post: 1547 fcwrap.write(indent + " " + a.cwrap_post) 1548 if rtype: 1549 fcwrap.write(indent + " " + "return result_api_;\n") 1550 fcwrap.write(indent + "}\n\n") 1551 for m in module.submodules: 1552 write_module(m, c_namespace, cpp_namespace, indent) 1553 fcwrap.write(indent[:-2] + "} // namespace " + module.name + 1554 "\n\n") 1555 1556 self.current_lineno = 1 1557 with open(ns + "c.h", "w") as f: 1558 with open(ns + "c.cpp", "w") as fc: 1559 with open(ns + ".h_cwrap", "w") as fcwrap: 1560 self.fwrite( 1561 f, 1562 c_header.format(self.copyright, self.issues, 1563 ns.upper(), self.code, 1564 self.version_major, self.version_minor, 1565 self.version_patch, ns)) 1566 fc.write( 1567 c_cpp_header.format(self.copyright, self.issues, ns, 1568 ns.upper(), self.code)) 1569 fc.write(cwrap_utils.format(ns, "")) 1570 fc.write(c_cpp_utils.format(ns)) 1571 fc.write("\n") 1572 fcwrap.write( 1573 cwrap_header.format(self.copyright, self.issues, 1574 ns.upper(), self.code, 1575 self.version_major, 1576 self.version_minor, 1577 self.version_patch, ns)) 1578 fcwrap.write("namespace " + ns + " {\n") 1579 s = cwrap_utils.format(ns, "inline ").split('\n') 1580 for line in s: 1581 fcwrap.write(" " + line + "\n") 1582 fcwrap.write(" inline void throwLastError()\n") 1583 fcwrap.write(" {\n") 1584 fcwrap.write(' int ierr = 0;\n') 1585 fcwrap.write(' char *api_error_;\n') 1586 fcwrap.write( 1587 ' gmshLoggerGetLastError(&api_error_, &ierr);\n') 1588 fcwrap.write( 1589 ' if(ierr) throw "Could not get last error";\n') 1590 fcwrap.write( 1591 ' std::string error = std::string(api_error_);\n') 1592 fcwrap.write(' gmshFree(api_error_);\n') 1593 fcwrap.write(' throw error;\n') 1594 fcwrap.write(" }\n\n") 1595 fcwrap.write("}\n\n") 1596 for module in self.modules: 1597 write_module(module, "", "", "") 1598 self.fwrite(f, c_footer) 1599 fcwrap.write(cwrap_footer) 1600 1601 def write_python(self): 1602 def parg(a): 1603 return a.name + (("=" + a.python_value) if a.python_value else "") 1604 1605 def write_function(f, fun, c_mpath, py_mpath, indent): 1606 (rtype, name, args, doc, special) = fun 1607 if "onlycc++" in special: return 1608 if "nopython" in special: return 1609 iargs = list(a for a in args if not a.out) 1610 oargs = list(a for a in args if a.out) 1611 self.fwrite(f, "\n") 1612 if c_mpath != ns: 1613 self.fwrite(f, indent + "@staticmethod\n") 1614 self.flog('py', py_mpath.replace('.', '/') + name) 1615 self.fwrite( 1616 f, indent + "def " + name + "(" + ", ".join( 1617 (parg(a) for a in iargs)) + "):\n") 1618 ind = indent + " " 1619 self.fwrite(f, ind + '"""\n') 1620 self.fwrite( 1621 f, ind + py_mpath + name + "(" + 1622 ", ".join(parg(a) for a in iargs) + ")\n\n") 1623 self.fwrite( 1624 f, 1625 ind + ("\n" + ind).join(textwrap.wrap(doc, 75)) + "\n") 1626 if rtype or oargs: 1627 self.fwrite( 1628 f, "\n" + ind + "Return " + 1629 ", ".join(([("an " if rtype.rtexi_type == 1630 "integer value" else "a ") + 1631 rtype.rtexi_type] if rtype else []) + 1632 [("`" + a.name + "'") for a in oargs]) + ".\n") 1633 self.fwrite(f, ind + '"""\n') 1634 for a in args: 1635 if a.python_pre: self.fwrite(f, ind + a.python_pre + "\n") 1636 self.fwrite(f, ind + "ierr = c_int()\n") 1637 c_name = c_mpath + name[0].upper() + name[1:] 1638 if rtype is odouble: 1639 self.fwrite(f, ind + "lib." + c_name + ".restype = c_double\n") 1640 self.fwrite( 1641 f, ind + "api_result_ = " if 1642 ((rtype is oint) or (rtype is odouble)) else (ind)) 1643 self.fwrite( 1644 f, "lib." + c_name + "(\n " + ind + 1645 (",\n" + ind + " ").join( 1646 tuple((a.python_arg 1647 for a in args)) + ("byref(ierr)", )) + ")\n") 1648 if name == "finalize": # special case for finalize() function 1649 self.fwrite(f, ind + "if oldsig is not None:\n") 1650 self.fwrite( 1651 f, ind + " signal.signal(signal.SIGINT, oldsig)\n") 1652 self.fwrite(f, ind + "if ierr.value != 0:\n") 1653 if name == "getLastError": # special case for getLastError() function 1654 self.fwrite( 1655 f, ind + 1656 " raise Exception('Could not get last error')\n") 1657 else: 1658 self.fwrite( 1659 f, ind + " raise Exception(logger.getLastError())\n") 1660 r = (["api_result_"]) if rtype else [] 1661 r += list((o.python_return for o in oargs)) 1662 if len(r) != 0: 1663 if len(r) == 1: 1664 self.fwrite(f, ind + "return " + r[0] + "\n") 1665 else: 1666 self.fwrite( 1667 f, ind + "return (\n" + ind + " " + 1668 (",\n" + ind + " ").join(r) + ")\n") 1669 # define alias with underscore (standard python style) 1670 name_ = re.sub('([A-Z]+)', r'_\1', name).lower() 1671 if name != name_: 1672 self.fwrite(f, indent + name_ + " = " + name + "\n") 1673 1674 def write_module(f, m, c_mpath, py_mpath, indent): 1675 if c_mpath: 1676 c_mpath += m.name[0].upper() + m.name[1:] 1677 py_mpath += m.name + "." 1678 else: 1679 c_mpath = m.name 1680 py_mpath = m.name + "." 1681 for fun in m.fs: 1682 write_function(f, fun, c_mpath, py_mpath, indent) 1683 for module in m.submodules: 1684 self.fwrite(f, 1685 "\n\n" + indent + "class " + module.name + ":\n") 1686 indentm = indent + " " 1687 self.fwrite(f, indentm + '"""\n') 1688 self.fwrite( 1689 f, indentm + ("\n" + indentm).join( 1690 textwrap.wrap(capi(module.doc), 75)) + "\n") 1691 self.fwrite(f, indentm + '"""\n') 1692 write_module(f, module, c_mpath, py_mpath, indentm) 1693 1694 self.current_lineno = 1 1695 with open(ns + ".py", "w") as f: 1696 self.fwrite( 1697 f, 1698 python_header.format(self.copyright, self.issues, self.code, 1699 self.version_major, self.version_minor, 1700 self.version_patch, ns.upper(), ns)) 1701 for module in self.modules: 1702 write_module(f, module, "", "", "") 1703 1704 def write_julia(self): 1705 def parg(a): 1706 return a.name + ((" = " + a.julia_value) if a.julia_value else "") 1707 1708 def write_function(f, fun, c_mpath, jl_mpath): 1709 (rtype, name, args, doc, special) = fun 1710 if "onlycc++" in special: return 1711 if "nojulia" in special: return 1712 iargs = list(a for a in args if not a.out) 1713 oargs = list(a for a in args if a.out) 1714 self.fwrite(f, '\n"""\n ') 1715 self.fwrite( 1716 f, jl_mpath + name + "(" + ", ".join(parg(a) 1717 for a in iargs) + ")\n\n") 1718 self.fwrite( 1719 f, "\n".join(textwrap.wrap(doc, 80)).replace("'", "`") + "\n") 1720 if rtype or oargs: 1721 self.fwrite( 1722 f, "\nReturn " + 1723 ", ".join(([("an " if rtype.rtexi_type == 1724 "integer value" else "a ") + 1725 rtype.rtexi_type] if rtype else []) + 1726 [("`" + a.name + "`") for a in oargs]) + ".\n") 1727 self.fwrite(f, '"""\n') 1728 self.flog('jl', jl_mpath.replace('.', '/') + name) 1729 self.fwrite( 1730 f, "function " + name + "(" + ", ".join( 1731 (parg(a) for a in iargs)) + ")\n") 1732 for a in args: 1733 if a.julia_pre: self.fwrite(f, " " + a.julia_pre + "\n") 1734 self.fwrite(f, " ierr = Ref{Cint}()\n ") 1735 self.fwrite( 1736 f, "api_result_ = " if 1737 ((rtype is oint) or (rtype is odouble)) else "") 1738 c_name = c_mpath + name[0].upper() + name[1:] 1739 self.fwrite( 1740 f, "ccall((:" + c_name + ", " + 1741 ("" if c_mpath == ns else ns + ".") + "lib), " + 1742 ("Cvoid" if rtype is None else rtype.rjulia_type) + ",\n" + 1743 " " * 10 + "(" + ", ".join( 1744 (tuple(a.julia_ctype for a in args) + ("Ptr{Cint}", ))) + 1745 ("," if not len(args) else "") + "),\n" + " " * 10 + 1746 ", ".join(tuple(a.julia_arg 1747 for a in args) + ("ierr", )) + ")\n") 1748 if name == "getLastError": # special case for getLastError() function 1749 self.fwrite( 1750 f, 1751 ' ierr[] != 0 && error("Could not get last error")\n') 1752 else: 1753 self.fwrite( 1754 f, 1755 ' ierr[] != 0 && error(gmsh.logger.getLastError())\n') 1756 for a in args: 1757 if a.julia_post: self.fwrite(f, " " + a.julia_post + "\n") 1758 r = (["api_result_"]) if rtype else [] 1759 r += list((o.julia_return for o in oargs)) 1760 self.fwrite(f, " return ") 1761 if len(r) == 0: 1762 self.fwrite(f, "nothing") 1763 else: 1764 self.fwrite(f, ", ".join(r)) 1765 self.fwrite(f, "\nend\n") 1766 # define alias with underscore (closer to Julia style) 1767 name_ = re.sub('([A-Z]+)', r'_\1', name).lower() 1768 if name != name_: 1769 self.fwrite(f, "const " + name_ + " = " + name + "\n") 1770 1771 def write_module(f, m, c_mpath, jl_mpath, level): 1772 self.fwrite(f, '\n"""\n ') 1773 self.fwrite(f, "module " + jl_mpath + m.name + "\n\n") 1774 self.fwrite(f, "\n".join(textwrap.wrap(capi(m.doc), 80)) + "\n") 1775 self.fwrite(f, '"""\n') 1776 self.fwrite(f, "module " + m.name + "\n\n") 1777 if level == 1: 1778 self.fwrite( 1779 f, 'const {0}_API_VERSION = "{1}.{2}.{3}"\n'.format( 1780 ns.upper(), self.version_major, self.version_minor, 1781 self.version_patch)) 1782 self.fwrite( 1783 f, 'const {0}_API_VERSION_MAJOR = {1}\n'.format( 1784 ns.upper(), self.version_major)) 1785 self.fwrite( 1786 f, 'const {0}_API_VERSION_MINOR = {1}\n'.format( 1787 ns.upper(), self.version_minor)) 1788 self.fwrite( 1789 f, 'const {0}_API_VERSION_PATCH = {1}\n'.format( 1790 ns.upper(), self.version_patch)) 1791 self.fwrite(f, 'const libdir = dirname(@__FILE__)\n') 1792 self.fwrite( 1793 f, 'const libname = Sys.iswindows() ? "' + ns + 1794 '-{0}.{1}'.format(self.version_major, self.version_minor) + 1795 '.dll" : "lib' + ns + '"\n') 1796 self.fwrite(f, 'import Libdl\n') 1797 self.fwrite( 1798 f, 'const lib = Libdl.find_library([libname], [libdir])\n') 1799 else: 1800 self.fwrite(f, "import " + ("." * level) + ns + "\n") 1801 if c_mpath: 1802 c_mpath += m.name[0].upper() + m.name[1:] 1803 jl_mpath += m.name + "." 1804 else: 1805 c_mpath = m.name 1806 jl_mpath = m.name + "." 1807 for fun in m.fs: 1808 write_function(f, fun, c_mpath, jl_mpath) 1809 for module in m.submodules: 1810 write_module(f, module, c_mpath, jl_mpath, level + 1) 1811 self.fwrite(f, "\nend # end of module " + m.name + "\n") 1812 1813 self.current_lineno = 1 1814 with open(ns + ".jl", "w") as f: 1815 self.fwrite( 1816 f, 1817 julia_header.format(self.copyright, self.issues, self.code, 1818 self.version_major, self.version_minor, 1819 self.version_patch)) 1820 for module in self.modules: 1821 write_module(f, module, "", "", 1) 1822 1823 1824 def write_fortran(self): 1825 def write_module(module, c_namespace, cpp_namespace, indent): 1826 cpp_namespace += module.name + "::" 1827 if c_namespace: 1828 c_namespace += module.name[0].upper() + module.name[1:] 1829 else: 1830 c_namespace = module.name 1831 1832 indent += " " 1833 for rtype, name, args, doc, special in module.fs: 1834 # *f.h 1835 fname = c_namespace + name[0].upper() + name[1:] 1836 1837# output doc 1838 self.fwrite( 1839 f, 1840 "\n! " + "\n! ".join(textwrap.wrap(doc, 75)) + "\n") 1841 fnameapi = "! " + ns.upper() + "_API " + (rtype.rc_type if rtype else 1842 "void") + " " + fname + "(" 1843 self.flog('f', cpp_namespace.replace('::', '/') + name) 1844 1845 if (len(fname) < 45) : 1846 1847# output fortran header 1848 fnamef = ' '*8 + ("function" if rtype else "subroutine") + ' ' + fname + "(" 1849 self.fwrite( 1850 f, fnamef + "\n & " + (",\n & ").join( 1851 list((a.fortran_name_pre + a.name + a.fortran_name_post for a in args + (oint("ierr"), )))) + ")\n") 1852 1853 left = " " 1854 self.fwrite( 1855 f, 1856 " & bind(C, name = \"" + fname + "\")" + "\n") 1857 self.fwrite( 1858 f, 1859 left + "use, intrinsic :: iso_c_binding" + "\n") 1860 if rtype : 1861 self.fwrite( 1862 f, 1863 left + (rtype.fortran_type) + "::" + fname + "\n") 1864 1865 self.fwrite( 1866 f, ("").join( 1867 list(( left + " " + a.fortran_type + "::" 1868 + a.name + a.fortran_type_post 1869 + "\n" for a in args + (oint("ierr"), ) )) 1870 ) 1871 ) 1872 1873 self.fwrite( 1874 f, 1875 left + "end " + ("function" if rtype else "subroutine") 1876 + " " + fname + "\n") 1877 1878 for m in module.submodules: 1879 write_module(m, c_namespace, cpp_namespace, indent) 1880 1881 self.current_lineno = 1 1882 with open(ns + "f.h", "w") as f: 1883 self.fwrite( 1884 f, 1885 fortran_header.format(self.copyright, self.issues, 1886 ns.upper(), self.code, 1887 self.version_major, self.version_minor, 1888 self.version_patch, ns)) 1889 for module in self.modules: 1890 write_module(module, "", "", "") 1891 self.fwrite(f, fortran_footer) 1892 1893 1894 def write_texi(self): 1895 def tryint(s): 1896 try: 1897 return int(s) 1898 except: 1899 return s 1900 1901 def alphanum_key(s): 1902 return [tryint(c) for c in re.split('([0-9]+)', s)] 1903 1904 def get_file_data(path, ext): 1905 data = [] 1906 for r, d, f in os.walk(path): 1907 for file in f: 1908 if file.endswith(ext): 1909 filename = os.path.join(r, file) 1910 contents = [] 1911 for line in open(filename, 'r'): 1912 contents.append(line) 1913 data.append([filename, contents]) 1914 data.sort(key=lambda x: alphanum_key(x[0])) 1915 return data 1916 1917 def find_function(lang, name, data): 1918 only_unique = False # only report unique matches? 1919 in_comments = False # report matches in comments? 1920 if lang == 'Python': 1921 func = name.replace('/', '.') 1922 comment = '#' 1923 else: 1924 func = name.replace('/', '::') 1925 comment = '//' 1926 match = [] 1927 unique = set() 1928 for file in data: 1929 l = 0 1930 for line in file[1]: 1931 l = l + 1 1932 # allow white space between func name and ( 1933 if re.search(func + '\s*\(', line): 1934 strip = re.sub(r'\s+', '', line) 1935 # don't report matches in comments 1936 if not in_comments and strip.startswith(comment): 1937 continue 1938 # only report a given match once 1939 if (not only_unique) or (strip not in unique): 1940 match.append((file[0], l)) 1941 unique.add(strip) 1942 break # report only one match per file 1943 else: 1944 unique.add(strip) 1945 return match 1946 1947 def write_module(module, path, node, node_next, node_prev, cpp_data, 1948 py_data): 1949 f.write("@node " + node + ", " + node_next + ", " + node_prev + 1950 ", Gmsh API\n") 1951 f.write("@section Namespace @code{" + path + "}: " + module.doc + 1952 "\n\n") 1953 f.write("@ftable @code\n") 1954 for rtype, name, args, doc, special in module.fs: 1955 tfull = path + '/' + name 1956 if len(tfull) > 40: # insert discretionary hyphen if too long 1957 for i in range(40, len(tfull)): 1958 if tfull[i].isupper(): 1959 tfull = tfull[:i] + '@-' + tfull[i:] 1960 break 1961 f.write("@item " + tfull + "\n") 1962 tdoc = doc.replace("`", "@code{").replace("'", "}") 1963 f.write("\n".join(textwrap.wrap(tdoc, 80)) + "\n\n") 1964 f.write("@table @asis\n") 1965 iargs = list(a for a in args if not a.out) 1966 oargs = list(a for a in args if a.out) 1967 f.write("@item " + "Input:\n" + (", ".join( 1968 ("@code{" + iarg.texi + "}") 1969 for iarg in iargs) if len(iargs) else "-") + "\n") 1970 f.write("@item " + "Output:\n" + (", ".join( 1971 ("@code{" + oarg.name + "}") 1972 for oarg in oargs) if len(oargs) else "-") + "\n") 1973 f.write("@item " + "Return:\n" + 1974 (rtype.rtexi_type if rtype else "-") + "\n") 1975 f.write("@item " + "Language-specific definition:\n") 1976 f.write("@url{@value{GITLAB-PREFIX}/api/gmsh.h#L" + 1977 str(self.api_lineno['cpp'][path + '/' + name]) + 1978 ",C++}") 1979 f.write(", @url{@value{GITLAB-PREFIX}/api/gmshc.h#L" + 1980 str(self.api_lineno['c'][path + '/' + name]) + ",C}") 1981 try: 1982 f.write(", @url{@value{GITLAB-PREFIX}/api/gmsh.py#L" + 1983 str(self.api_lineno['py'][path + '/' + name]) + 1984 ",Python}") 1985 except: 1986 pass 1987 try: 1988 f.write(", @url{@value{GITLAB-PREFIX}/api/gmsh.jl#L" + 1989 str(self.api_lineno['jl'][path + '/' + name]) + 1990 ",Julia}") 1991 except: 1992 pass 1993 f.write("\n") 1994 cpp = find_function('C++', path + '/' + name, cpp_data) 1995 py = find_function('Python', path + '/' + name, py_data) 1996 1997 def write_matches(lang, matches, max_matches): 1998 f.write(lang + ' (') 1999 for i in range(min(max_matches, 2000 len(matches))): # write max 5 matches 2001 if i > 0: f.write(', ') 2002 f.write('@url{@value{GITLAB-PREFIX}/' + 2003 matches[i][0][3:] + '#L' + str(matches[i][1]) + 2004 ',' + os.path.basename(matches[i][0]) + '}') 2005 if len(matches) > max_matches: f.write(', ...') 2006 f.write(')') 2007 2008 if len(cpp) or len(py): 2009 f.write("@item " + "Examples:\n") 2010 if len(cpp): 2011 write_matches("C++", cpp, 5) 2012 if len(py): f.write(', ') 2013 if len(py): 2014 write_matches("Python", py, 5) 2015 f.write("\n") 2016 f.write("@end table\n\n") 2017 f.write("@end ftable\n\n") 2018 2019 with open("../doc/texinfo/api.texi", "w") as f: 2020 f.write( 2021 "@c This file was generated by api/gen.py: do not edit manually!\n\n" 2022 ) 2023 2024 def flatten_module(flat, module, path): 2025 p = path + ("/" if len(path) else "") + module.name 2026 flat.append((module, p)) 2027 for m in module.submodules: 2028 flatten_module(flat, m, p) 2029 2030 def node_name(n): 2031 return "Namespace " + n[1] 2032 2033 flat = [] 2034 for m in self.modules: 2035 flatten_module(flat, m, "") 2036 N = len(flat) 2037 f.write("@menu\n") 2038 for i in range(N): 2039 f.write("* " + node_name(flat[i]) + "::\n") 2040 f.write("@end menu\n\n") 2041 cpp_data = get_file_data('../tutorial', '.cpp') 2042 cpp_data.extend(get_file_data('../demos/api', '.cpp')) 2043 py_data = get_file_data('../tutorial', '.py') 2044 py_data.extend(get_file_data('../demos/api', '.py')) 2045 for i in range(N): 2046 write_module(flat[i][0], flat[i][1], node_name(flat[i]), 2047 "" if i == N - 1 else node_name(flat[i + 1]), 2048 "" if i == 0 else node_name(flat[i - 1]), 2049 cpp_data, py_data) 2050