Forked from
gmsh / gmsh
1027 commits behind the upstream repository.
-
Christophe Geuzaine authoredChristophe Geuzaine authored
GenApi.py 86.38 KiB
# Gmsh - Copyright (C) 1997-2022 C. Geuzaine, J.-F. Remacle
#
# See the LICENSE.txt file in the Gmsh root directory for license information.
# Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
# Contributor(s):
# Jonathan Lambrechts
import textwrap
import string
import os
import re
class arg:
def __init__(self, name, value, python_value, julia_value, cpp_type,
c_type, out):
self.name = name
self.value = value
self.out = out
self.cpp = cpp_type + " " + name + ((" = " + value) if value else "")
self.c_arg = name
self.c_pre = ""
self.c_post = ""
self.c = c_type + " " + name
self.cwrap_arg = self.name
self.cwrap_pre = ""
self.cwrap_post = ""
self.python_value = python_value if python_value is not None else value
self.python_arg = ""
self.python_return = ""
self.python_pre = ""
self.julia_value = julia_value if julia_value is not None else value
self.julia_arg = name
self.julia_ctype = ""
self.julia_pre = ""
self.julia_post = ""
self.julia_return = name
self.fortran_type_post = ""
self.fortran_name_pre = ""
self.fortran_name_post = ""
self.texi = name + (
(" = " + self.python_value) if self.python_value else "")
# input types
def ibool(name, value=None, python_value=None, julia_value=None):
a = arg(name, value, python_value, julia_value, "const bool", "const int",
False)
a.python_arg = "c_int(bool(" + name + "))"
a.cwrap_arg = "(int)" + name
a.julia_ctype = "Cint"
a.fortran_type = "integer(c_int), value"
return a
def iint(name, value=None, python_value=None, julia_value=None):
a = arg(name, value, python_value, julia_value, "const int", "const int",
False)
a.python_arg = "c_int(" + name + ")"
a.julia_ctype = "Cint"
a.fortran_type = "integer(c_int), value"
return a
def isize(name, value=None, python_value=None, julia_value=None):
a = arg(name, value, python_value, julia_value, "const std::size_t",
"const size_t", False)
a.python_arg = "c_size_t(" + name + ")"
a.julia_ctype = "Csize_t"
a.fortran_type = "integer(c_size_t), value"
return a
def idouble(name, value=None, python_value=None, julia_value=None):
a = arg(name, value, python_value, julia_value, "const double",
"const double", False)
a.python_arg = "c_double(" + name + ")"
a.julia_ctype = "Cdouble"
a.fortran_type = "real(c_double), value"
return a
def istring(name, value=None, python_value=None, julia_value=None):
a = arg(name, value, python_value, julia_value, "const std::string &",
"const char *", False)
a.python_arg = "c_char_p(" + name + ".encode())"
a.cwrap_arg = name + ".c_str()"
a.julia_ctype = "Ptr{Cchar}"
a.fortran_type = "character(len = 1, kind = c_char)"
a.fortran_type_post = "(*)"
return a
def ivoidstar(name, value=None, python_value=None, julia_value=None):
a = arg(name, value, python_value, julia_value, "const void *",
"const void *", False)
a.python_arg = "c_void_p(" + name + ")"
a.julia_ctype = "Ptr{Cvoid}"
a.fortran_type = "integer(c_int)"
a.fortran_type_post = "(*)"
return a
def ivectorint(name, value=None, python_value=None, julia_value=None):
if julia_value == "[]":
julia_value = "Cint[]"
a = arg(name, value, python_value, julia_value, "const std::vector<int> &",
"const int *", False)
api_name = "api_" + name + "_"
api_name_n = "api_" + name + "_n_"
a.c_pre = (" std::vector<int> " + api_name + "(" + name + ", " + name +
" + " + name + "_n);\n")
a.c_arg = api_name
a.c = "const int * " + name + ", const size_t " + name + "_n"
a.cwrap_pre = ("int *" + api_name + "; size_t " + api_name_n + "; " +
"vector2ptr(" + name + ", &" + api_name + ", &" +
api_name_n + ");\n")
a.cwrap_arg = api_name + ", " + api_name_n
a.cwrap_post = ns + "Free(" + api_name + ");\n"
a.python_pre = api_name + ", " + api_name_n + " = _ivectorint(" + name + ")"
a.python_arg = api_name + ", " + api_name_n
a.julia_ctype = "Ptr{Cint}, Csize_t"
a.julia_arg = "convert(Vector{Cint}, " + name + "), length(" + name + ")"
a.fortran_type = "integer(c_int)"
a.fortran_type_post = "(*)\n integer(c_size_t), value :: " + name + "_n"
a.fortran_name_post = ",\n & " + name + "_n"
return a
def ivectorsize(name, value=None, python_value=None, julia_value=None):
if julia_value == "[]":
julia_value = "Csize_t[]"
a = arg(name, value, python_value, julia_value,
"const std::vector<std::size_t> &", "const size_t *", False)
api_name = "api_" + name + "_"
api_name_n = "api_" + name + "_n_"
a.c_pre = (" std::vector<std::size_t> " + api_name + "(" + name + ", " +
name + " + " + name + "_n);\n")
a.c_arg = api_name
a.c = "const size_t * " + name + ", const size_t " + name + "_n"
a.cwrap_pre = ("size_t *" + api_name + "; size_t " + api_name_n + "; " +
"vector2ptr(" + name + ", &" + api_name + ", &" +
api_name_n + ");\n")
a.cwrap_arg = api_name + ", " + api_name_n
a.cwrap_post = ns + "Free(" + api_name + ");\n"
a.python_pre = api_name + ", " + api_name_n + " = _ivectorsize(" + name + ")"
a.python_arg = api_name + ", " + api_name_n
a.julia_ctype = "Ptr{Csize_t}, Csize_t"
a.julia_arg = "convert(Vector{Csize_t}, " + name + "), length(" + name + ")"
a.fortran_type = "integer(c_size_t)"
a.fortran_type_post = "(*)\n integer(c_size_t), value :: " + name + "_n"
a.fortran_name_post = ",\n & " + name + "_n"
return a
def ivectordouble(name, value=None, python_value=None, julia_value=None):
if julia_value == "[]":
julia_value = "Cdouble[]"
a = arg(name, value, python_value, julia_value,
"const std::vector<double> &", "const double * const *", False)
api_name = "api_" + name + "_"
api_name_n = "api_" + name + "_n_"
a.c_pre = (" std::vector<double> " + api_name + "(" + name + ", " +
name + " + " + name + "_n);\n")
a.c_arg = api_name
a.c = "const double * " + name + ", const size_t " + name + "_n"
a.cwrap_pre = ("double *" + api_name + "; size_t " + api_name_n + "; " +
"vector2ptr(" + name + ", &" + api_name + ", &" +
api_name_n + ");\n")
a.cwrap_arg = api_name + ", " + api_name_n
a.cwrap_post = ns + "Free(" + api_name + ");\n"
a.python_pre = api_name + ", " + api_name_n + " = _ivectordouble(" + name + ")"
a.python_arg = api_name + ", " + api_name_n
a.julia_ctype = "Ptr{Cdouble}, Csize_t"
a.julia_arg = "convert(Vector{Cdouble}, " + name + "), length(" + name + ")"
a.fortran_type = "real(c_double)"
a.fortran_type_post = "(*)\n integer(c_size_t), value :: " + name + "_n"
a.fortran_name_post = ",\n & " + name + "_n"
return a
def ivectorstring(name, value=None, python_value=None, julia_value=None):
a = arg(name, value, python_value, julia_value,
"const std::vector<std::string> &", "const char * const *", False)
api_name = "api_" + name + "_"
api_name_n = "api_" + name + "_n_"
a.c_pre = (" std::vector<std::string> " + api_name + "(" + name + ", " +
name + " + " + name + "_n);\n")
a.c_arg = api_name
a.c = "const char * const * " + name + ", const size_t " + name + "_n"
a.cwrap_pre = ("char **" + api_name + "; size_t " + api_name_n + "; " +
"vectorstring2charptrptr(" + name + ", &" + api_name +
", &" + api_name_n + ");\n")
a.cwrap_arg = api_name + ", " + api_name_n
a.cwrap_post = ("for(size_t i = 0; i < " + api_name_n + "; ++i){ " + ns +
"Free(" + api_name + "[i]); } " + ns + "Free(" + api_name +
");\n")
a.python_pre = api_name + ", " + api_name_n + " = _ivectorstring(" + name + ")"
a.python_arg = api_name + ", " + api_name_n
a.julia_ctype = "Ptr{Ptr{Cchar}}, Csize_t"
a.julia_arg = name + ", length(" + name + ")"
a.fortran_type = "type(c_ptr)"
a.fortran_type_post = "(*)\n integer(c_size_t), value :: " + name + "_n"
a.fortran_name_post = ",\n & " + name + "_n"
return a
def ivectorpair(name, value=None, python_value=None, julia_value=None):
if julia_value == "[]":
julia_value = "Tuple{Cint,Cint}[]"
a = arg(name, value, python_value, julia_value,
"const " + ns + "::vectorpair &", "const int *", False)
api_name = "api_" + name + "_"
api_name_n = "api_" + name + "_n_"
a.c_pre = (" " + ns + "::vectorpair " + api_name + "(" + name +
"_n/2);\n" + " for(size_t i = 0; i < " + name +
"_n/2; ++i){\n" + " " + api_name + "[i].first = " + name +
"[i * 2 + 0];\n" + " " + api_name + "[i].second = " +
name + "[i * 2 + 1];\n" + " }\n")
a.c_arg = api_name
a.c = "const int * " + name + ", const size_t " + name + "_n"
a.cwrap_pre = ("int *" + api_name + "; size_t " + api_name_n + "; " +
"vectorpair2intptr(" + name + ", &" + api_name + ", &" +
api_name_n + ");\n")
a.cwrap_arg = api_name + ", " + api_name_n
a.cwrap_post = ns + "Free(" + api_name + ");\n"
a.python_pre = api_name + ", " + api_name_n + " = _ivectorpair(" + name + ")"
a.python_arg = api_name + ", " + api_name_n
a.julia_ctype = "Ptr{Cint}, Csize_t"
a.julia_pre = (api_name + " = collect(Cint, Iterators.flatten(" + name +
"))\n " + api_name_n + " = length(" + api_name + ")")
a.julia_arg = (api_name + ", " + api_name_n)
a.fortran_type = "integer(c_int)"
a.fortran_type_post = "(*)\n integer(c_size_t), value :: " + name + "_n"
a.fortran_name_post = ",\n & " + name + "_n"
return a
def ivectorvectorint(name, value=None, python_value=None, julia_value=None):
if julia_value == "[]":
julia_value = "Vector{Cint}[]"
a = arg(name, value, python_value, julia_value,
"const std::vector<std::vector<int> > &", "const int * const *", False)
api_name = "api_" + name + "_"
api_name_n = "api_" + name + "_n_"
api_name_nn = "api_" + name + "_nn_"
a.c_pre = (" std::vector<std::vector<int> > " + api_name + "(" + name +
"_nn);\n" + " for(size_t i = 0; i < " + name +
"_nn; ++i)\n" + " " + api_name +
"[i] = std::vector<int>(" + name + "[i], " + name + "[i] + " +
name + "_n[i]);\n")
a.c_arg = api_name
a.c = ("const int * const * " + name + ", const size_t * " + name + "_n, " +
"const size_t " + name + "_nn")
a.cwrap_pre = ("int **" + api_name + "; size_t *" + api_name_n + ", " +
api_name_nn + "; " + "vectorvector2ptrptr(" + name + ", &" +
api_name + ", &" + api_name_n + ", &" + api_name_nn +
");\n")
a.cwrap_arg = api_name + ", " + api_name_n + ", " + api_name_nn
a.cwrap_post = ("for(size_t i = 0; i < " + api_name_nn + "; ++i){ " + ns +
"Free(" + api_name + "[i]); } " + ns + "Free(" + api_name +
"); " + ns + "Free(" + api_name_n + ");\n")
a.python_pre = (api_name + ", " + api_name_n + ", " + api_name_nn +
" = _ivectorvectorint(" + name + ")")
a.python_arg = api_name + ", " + api_name_n + ", " + api_name_nn
a.julia_ctype = "Ptr{Ptr{Cint}}, Ptr{Csize_t}, Csize_t"
a.julia_pre = (api_name_n + " = [ length(" + name +
"[i]) for i in 1:length(" + name + ") ]")
a.julia_arg = ("convert(Vector{Vector{Cint}}," + name + "), " +
api_name_n + ", length(" + name + ")")
a.fortran_type = "type(c_ptr), intent(out)"
a.fortran_type_post = ("\n type(c_ptr), intent(out) :: " + name +
"_n\n integer(c_size_t) :: " + name + "_nn")
a.fortran_name_post = ",\n & " + name + "_n,\n & " + name + "_nn"
return a
def ivectorvectorsize(name, value=None, python_value=None, julia_value=None):
if julia_value == "[]":
julia_value = "Vector{Csize_t}[]"
a = arg(name, value, python_value, julia_value,
"const std::vector<std::vector<std::size_t> > &",
"const size_t * const *", False)
api_name = "api_" + name + "_"
api_name_n = "api_" + name + "_n_"
api_name_nn = "api_" + name + "_nn_"
a.c_pre = (" std::vector<std::vector<std::size_t> > " + api_name + "(" +
name + "_nn);\n" + " for(size_t i = 0; i < " + name +
"_nn; ++i)\n" + " " + api_name +
"[i] = std::vector<std::size_t>(" + name + "[i], " + name +
"[i] + " + name + "_n[i]);\n")
a.c_arg = api_name
a.c = ("const size_t * const * " + name + ", const size_t * " + name + "_n, " +
"const size_t " + name + "_nn")
a.cwrap_pre = ("size_t **" + api_name + "; size_t *" + api_name_n + ", " +
api_name_nn + "; " + "vectorvector2ptrptr(" + name + ", &" +
api_name + ", &" + api_name_n + ", &" + api_name_nn +
");\n")
a.cwrap_arg = api_name + ", " + api_name_n + ", " + api_name_nn
a.cwrap_post = ("for(size_t i = 0; i < " + api_name_nn + "; ++i){ " + ns +
"Free(" + api_name + "[i]); } " + ns + "Free(" + api_name +
"); " + ns + "Free(" + api_name_n + ");\n")
a.python_pre = (api_name + ", " + api_name_n + ", " + api_name_nn +
" = _ivectorvectorsize(" + name + ")")
a.python_arg = api_name + ", " + api_name_n + ", " + api_name_nn
a.julia_ctype = "Ptr{Ptr{Csize_t}}, Ptr{Csize_t}, Csize_t"
a.julia_pre = (api_name_n + " = [ length(" + name +
"[i]) for i in 1:length(" + name + ") ]")
a.julia_arg = ("convert(Vector{Vector{Csize_t}}," + name + "), " +
api_name_n + ", length(" + name + ")")
a.fortran_type = "type(c_ptr), intent(out)"
a.fortran_type_post = ("\n type(c_ptr), intent(out) :: " + name +
"_n\n integer(c_size_t) :: " + name + "_nn")
a.fortran_name_post = ",\n & " + name + "_n,\n & " + name + "_nn"
return a
def ivectorvectordouble(name, value=None, python_value=None, julia_value=None):
if julia_value == "[]":
julia_value = "Vector{Cdouble}[]"
a = arg(name, value, python_value, julia_value,
"const std::vector<std::vector<double> > &", "const double * const *",
False)
api_name = "api_" + name + "_"
api_name_n = "api_" + name + "_n_"
api_name_nn = "api_" + name + "_nn_"
a.c_pre = (" std::vector<std::vector<double> > " + api_name + "(" +
name + "_nn);\n" + " for(size_t i = 0; i < " + name +
"_nn; ++i)\n" + " " + api_name +
"[i] = std::vector<double>(" + name + "[i], " + name +
"[i] + " + name + "_n[i]);\n")
a.c_arg = api_name
a.c = ("const double * const * " + name + ", const size_t * " + name + "_n, " +
"const size_t " + name + "_nn")
a.cwrap_pre = ("double **" + api_name + "; size_t *" + api_name_n + ", " +
api_name_nn + "; " + "vectorvector2ptrptr(" + name + ", &" +
api_name + ", &" + api_name_n + ", &" + api_name_nn +
");\n")
a.cwrap_arg = api_name + ", " + api_name_n + ", " + api_name_nn
a.cwrap_post = ("for(size_t i = 0; i < " + api_name_nn + "; ++i){ " + ns +
"Free(" + api_name + "[i]); } " + ns + "Free(" + api_name +
"); " + ns + "Free(" + api_name_n + ");\n")
a.python_pre = (api_name + ", " + api_name_n + ", " + api_name_nn +
" = _ivectorvectordouble(" + name + ")")
a.python_arg = api_name + ", " + api_name_n + ", " + api_name_nn
a.julia_ctype = "Ptr{Ptr{Cdouble}}, Ptr{Csize_t}, Csize_t"
a.julia_pre = (api_name_n + " = [ length(" + name +
"[i]) for i in 1:length(" + name + ") ]")
a.julia_arg = ("convert(Vector{Vector{Cdouble}}," + name + "), " +
api_name_n + ", length(" + name + ")")
a.fortran_type = "type(c_ptr), intent(out)"
a.fortran_type_post = ("\n type(c_ptr), intent(out) :: " +
name + "_n\n integer(c_size_t) :: " + name + "_nn")
a.fortran_name_post = ",\n & " + name + "_n,\n & " + name + "_nn"
return a
# output types
class oint(arg):
rcpp_type = "int"
rc_type = "int"
rtexi_type = "integer value"
rjulia_type = "Cint"
fortran_type = "integer(c_int)"
fortran_type_post = ""
def __init__(self, name, value=None, python_value=None, julia_value=None):
arg.__init__(self, name, value, python_value, julia_value, "int &",
"int *", True)
api_name = "api_" + name + "_"
self.c_arg = "*" + name
self.cwrap_arg = "&" + name
self.python_pre = api_name + " = c_int()"
self.python_arg = "byref(" + api_name + ")"
self.python_return = api_name + ".value"
self.julia_ctype = "Ptr{Cint}"
self.julia_pre = api_name + " = Ref{Cint}()"
self.julia_arg = api_name
self.julia_return = api_name + "[]"
class osize(arg):
rcpp_type = "std::size_t"
rc_type = "size_t"
rtexi_type = "size value"
rjulia_type = "Csize_t"
fortran_type = "integer(c_size_t)"
fortran_type_post = ""
def __init__(self, name, value=None, python_value=None, julia_value=None):
arg.__init__(self, name, value, python_value, julia_value,
"std::size_t &", "size_t *", True)
api_name = "api_" + name + "_"
self.c_arg = "*" + name
self.cwrap_arg = "&" + name
self.python_pre = api_name + " = c_size_t()"
self.python_arg = "byref(" + api_name + ")"
self.python_return = api_name + ".value"
self.julia_ctype = "Ptr{Csize_t}"
self.julia_pre = api_name + " = Ref{Csize_t}()"
self.julia_arg = api_name
self.julia_return = api_name + "[]"
class odouble(arg):
rcpp_type = "double"
rc_type = "double"
rtexi_type = "floating point value"
rjulia_type = "Cdouble"
fortran_type = "real(c_double)"
fortran_type_post = ""
def __init__(self, name, value=None, python_value=None, julia_value=None):
arg.__init__(self, name, value, python_value, julia_value, "double &",
"double *", True)
api_name = "api_" + name + "_"
self.c_arg = "*" + name
self.cwrap_arg = "&" + name
self.python_pre = api_name + " = c_double()"
self.python_arg = "byref(" + api_name + ")"
self.python_return = api_name + ".value"
self.julia_ctype = "Ptr{Cdouble}"
self.julia_pre = api_name + " = Ref{Cdouble}()"
self.julia_arg = api_name
self.julia_return = api_name + "[]"
def ostring(name, value=None, python_value=None, julia_value=None):
a = arg(name, value, python_value, julia_value, "std::string &", "char **",
True)
api_name = "api_" + name + "_"
a.c_pre = " std::string " + api_name + ";\n"
a.c_arg = api_name
a.c_post = " *" + name + " = strdup(" + api_name + ".c_str());\n"
a.cwrap_pre = "char *" + api_name + ";\n"
a.cwrap_arg = "&" + api_name
a.cwrap_post = (name + " = std::string(" + api_name + "); " + ns +
"Free(" + api_name + ");\n")
a.python_pre = api_name + " = c_char_p()"
a.python_arg = "byref(" + api_name + ")"
a.python_return = "_ostring(" + api_name + ")"
a.julia_ctype = "Ptr{Ptr{Cchar}}"
a.julia_pre = api_name + " = Ref{Ptr{Cchar}}()"
a.julia_arg = api_name
a.julia_post = name + " = unsafe_string(" + api_name + "[])"
a.fortran_type = "type(c_ptr)"
a.fortran_type_post = "(*)"
return a
def ovectorint(name, value=None, python_value=None, julia_value=None):
a = arg(name, value, python_value, julia_value, "std::vector<int> &",
"int **", True)
api_name = "api_" + name + "_"
api_name_n = api_name + "n_"
a.c_pre = " std::vector<int> " + api_name + ";\n"
a.c_arg = api_name
a.c_post = " vector2ptr(" + api_name + ", " + name + ", " + name + "_n);\n"
a.c = "int ** " + name + ", size_t * " + name + "_n"
a.cwrap_pre = "int *" + api_name + "; size_t " + api_name_n + ";\n"
a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n
a.cwrap_post = (name + ".assign(" + api_name + ", " + api_name + " + " +
api_name_n + "); " + ns + "Free(" + api_name + ");\n")
a.python_pre = api_name + ", " + api_name_n + " = POINTER(c_int)(), c_size_t()"
a.python_arg = "byref(" + api_name + "), byref(" + api_name_n + ")"
a.python_return = "_ovectorint(" + api_name + ", " + api_name_n + ".value)"
a.julia_ctype = "Ptr{Ptr{Cint}}, Ptr{Csize_t}"
a.julia_pre = (api_name + " = Ref{Ptr{Cint}}()\n " + api_name_n +
" = Ref{Csize_t}()")
a.julia_arg = api_name + ", " + api_name_n
a.julia_post = (name + " = unsafe_wrap(Array, " + api_name + "[], " +
api_name_n + "[], own = true)")
a.fortran_type = "type(c_ptr), intent(out)"
a.fortran_type_post = "\n integer(c_size_t) :: " + name +"_n"
a.fortran_name_post = ",\n & " + name + "_n"
return a
def ovectorsize(name, value=None, python_value=None, julia_value=None):
a = arg(name, value, python_value, julia_value,
"std::vector<std::size_t> &", "size_t **", True)
api_name = "api_" + name + "_"
api_name_n = api_name + "n_"
a.c_pre = " std::vector<std::size_t> " + api_name + ";\n"
a.c_arg = api_name
a.c_post = " vector2ptr(" + api_name + ", " + name + ", " + name + "_n);\n"
a.c = "size_t ** " + name + ", size_t * " + name + "_n"
a.cwrap_pre = "size_t *" + api_name + "; size_t " + api_name_n + ";\n"
a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n
a.cwrap_post = (name + ".assign(" + api_name + ", " + api_name + " + " +
api_name_n + "); " + ns + "Free(" + api_name + ");\n")
a.python_pre = api_name + ", " + api_name_n + " = POINTER(c_size_t)(), c_size_t()"
a.python_arg = "byref(" + api_name + "), byref(" + api_name_n + ")"
a.python_return = "_ovectorsize(" + api_name + ", " + api_name_n + ".value)"
a.julia_ctype = "Ptr{Ptr{Csize_t}}, Ptr{Csize_t}"
a.julia_pre = (api_name + " = Ref{Ptr{Csize_t}}()\n " + api_name_n +
" = Ref{Csize_t}()")
a.julia_arg = api_name + ", " + api_name_n
a.julia_post = (name + " = unsafe_wrap(Array, " + api_name + "[], " +
api_name_n + "[], own = true)")
a.fortran_type = "type(c_ptr), intent(out)"
a.fortran_type_post = "\n integer(c_size_t) :: " + name + "_n"
a.fortran_name_post = ",\n & " + name + "_n"
return a
def ovectordouble(name, value=None, python_value=None, julia_value=None):
a = arg(name, value, python_value, julia_value, "std::vector<double> &",
"double *", True)
api_name = "api_" + name + "_"
api_name_n = api_name + "n_"
a.c_pre = " std::vector<double> " + api_name + ";\n"
a.c_arg = api_name
a.c_post = " vector2ptr(" + api_name + ", " + name + ", " + name + "_n);\n"
a.c = "double ** " + name + ", size_t * " + name + "_n"
a.cwrap_pre = "double *" + api_name + "; size_t " + api_name_n + ";\n"
a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n
a.cwrap_post = (name + ".assign(" + api_name + ", " + api_name + " + " +
api_name_n + "); " + ns + "Free(" + api_name + ");\n")
a.python_pre = api_name + ", " + api_name_n + " = POINTER(c_double)(), c_size_t()"
a.python_arg = "byref(" + api_name + "), byref(" + api_name_n + ")"
a.python_return = "_ovectordouble(" + api_name + ", " + api_name_n + ".value)"
a.julia_ctype = "Ptr{Ptr{Cdouble}}, Ptr{Csize_t}"
a.julia_pre = (api_name + " = Ref{Ptr{Cdouble}}()\n " + api_name_n +
" = Ref{Csize_t}()")
a.julia_arg = api_name + ", " + api_name_n
a.julia_post = (name + " = unsafe_wrap(Array, " + api_name + "[], " +
api_name_n + "[], own = true)")
a.fortran_type = "type(c_ptr), intent(out)"
a.fortran_type_post = "\n integer(c_size_t) :: " + name + "_n"
a.fortran_name_post = ",\n & " + name + "_n"
return a
def ovectorstring(name, value=None, python_value=None, julia_value=None):
a = arg(name, value, python_value, julia_value,
"std::vector<std::string> &", "char **", True)
api_name = "api_" + name + "_"
api_name_n = api_name + "n_"
a.c_pre = " std::vector<std::string> " + api_name + ";\n"
a.c_arg = api_name
a.c_post = (" vectorstring2charptrptr(" + api_name + ", " + name +
", " + name + "_n);\n")
a.c = "char *** " + name + ", size_t * " + name + "_n"
a.cwrap_pre = "char **" + api_name + "; size_t " + api_name_n + ";\n"
a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n
a.cwrap_post = (name + ".resize(" + api_name_n + "); " +
"for(size_t i = 0; i < " + api_name_n + "; ++i){ " + name +
"[i] = std::string(" + api_name + "[i]); " + ns + "Free(" +
api_name + "[i]); } " + ns + "Free(" + api_name + ");\n")
a.python_pre = api_name + ", " + api_name_n + " = POINTER(POINTER(c_char))(), c_size_t()"
a.python_arg = "byref(" + api_name + "), byref(" + api_name_n + ")"
a.python_return = "_ovectorstring(" + api_name + ", " + api_name_n + ".value)"
a.julia_ctype = "Ptr{Ptr{Ptr{Cchar}}}, Ptr{Csize_t}"
a.julia_pre = (api_name + " = Ref{Ptr{Ptr{Cchar}}}()\n " + api_name_n +
" = Ref{Csize_t}()")
a.julia_arg = api_name + ", " + api_name_n
a.julia_post = ("tmp_" + api_name + " = unsafe_wrap(Array, " + api_name +
"[], " + api_name_n + "[], own = true)\n " + name +
" = [unsafe_string(tmp_" + api_name +
"[i]) for i in 1:length(tmp_" + api_name + ") ]")
a.fortran_type = "type(c_ptr), intent(out)"
a.fortran_type_post = "\n integer(c_size_t) :: " + name + "_n"
a.fortran_name_post = ",\n & " + name + "_n"
return a
def ovectorpair(name, value=None, python_value=None, julia_value=None):
a = arg(name, value, python_value, julia_value, ns + "::vectorpair &",
"int **", True)
api_name = "api_" + name + "_"
api_name_n = api_name + "n_"
a.c_pre = " " + ns + "::vectorpair " + api_name + ";\n"
a.c_arg = api_name
a.c_post = " vectorpair2intptr(" + api_name + ", " + name + ", " + name + "_n);\n"
a.c = "int ** " + name + ", size_t * " + name + "_n"
a.cwrap_pre = "int *" + api_name + "; size_t " + api_name_n + ";\n"
a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n
a.cwrap_post = (name + ".resize(" + api_name_n + " / 2); " +
"for(size_t i = 0; i < " + api_name_n + " / 2; ++i){ " +
name + "[i].first = " + api_name + "[i * 2 + 0]; " + name +
"[i].second = " + api_name + "[i * 2 + 1]; } " + ns +
"Free(" + api_name + ");\n")
a.python_pre = api_name + ", " + api_name_n + " = POINTER(c_int)(), c_size_t()"
a.python_arg = "byref(" + api_name + "), byref(" + api_name_n + ")"
a.python_return = "_ovectorpair(" + api_name + ", " + api_name_n + ".value)"
a.julia_ctype = "Ptr{Ptr{Cint}}, Ptr{Csize_t}"
a.julia_pre = (api_name + " = Ref{Ptr{Cint}}()\n " + api_name_n +
" = Ref{Csize_t}()")
a.julia_arg = api_name + ", " + api_name_n
a.julia_post = ("tmp_" + api_name + " = unsafe_wrap(Array, " + api_name +
"[], " + api_name_n + "[], own = true)\n " + name +
" = [ (tmp_" + api_name + "[i], tmp_" + api_name +
"[i+1]) " + "for i in 1:2:length(tmp_" + api_name + ") ]")
a.fortran_type = "type(c_ptr), intent(out)"
a.fortran_type_post = "\n integer(c_size_t) :: " + name + "_n"
a.fortran_name_post = ",\n & " + name + "_n"
return a
def ovectorvectorint(name, value=None, python_value=None, julia_value=None):
a = arg(name, value, python_value, julia_value,
"std::vector<std::vector<int> > &", "int **", True)
api_name = "api_" + name + "_"
api_name_n = api_name + "n_"
api_name_nn = api_name + "nn_"
a.c_pre = " std::vector<std::vector<int> > " + api_name + ";\n"
a.c_arg = api_name
a.c_post = (" vectorvector2ptrptr(" + api_name + ", " + name + ", " +
name + "_n, " + name + "_nn);\n")
a.c = "int *** " + name + ", size_t ** " + name + "_n, size_t *" + name + "_nn"
a.cwrap_pre = "int **" + api_name + "; size_t *" + api_name_n + ", " + api_name_nn + ";\n"
a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n + ", " + "&" + api_name_nn
a.cwrap_post = (name + ".resize(" + api_name_nn + "); " +
"for(size_t i = 0; i < " + api_name_nn + "; ++i){ " +
name + "[i].assign(" + api_name + "[i], " + api_name +
"[i] + " + api_name_n + "[i]); " + ns + "Free(" +
api_name + "[i]); } " + ns + "Free(" + api_name + "); " +
ns + "Free(" + api_name_n + ");\n")
a.python_pre = (
api_name + ", " + api_name_n + ", " + api_name_nn +
" = POINTER(POINTER(c_int))(), POINTER(c_size_t)(), c_size_t()")
a.python_arg = ("byref(" + api_name + "), byref(" + api_name_n +
"), byref(" + api_name_nn + ")")
a.python_return = ("_ovectorvectorint(" + api_name + ", " + api_name_n +
", " + api_name_nn + ")")
a.julia_ctype = "Ptr{Ptr{Ptr{Cint}}}, Ptr{Ptr{Csize_t}}, Ptr{Csize_t}"
a.julia_pre = (api_name + " = Ref{Ptr{Ptr{Cint}}}()\n " + api_name_n +
" = Ref{Ptr{Csize_t}}()\n " + api_name_nn +
" = Ref{Csize_t}()")
a.julia_arg = api_name + ", " + api_name_n + ", " + api_name_nn
a.julia_post = ("tmp_" + api_name + " = unsafe_wrap(Array, " + api_name +
"[], " + api_name_nn + "[], own = true)\n " + "tmp_" +
api_name_n + " = unsafe_wrap(Array, " + api_name_n +
"[], " + api_name_nn + "[], own = true)\n " + name +
" = [ unsafe_wrap(Array, tmp_" + api_name + "[i], " +
"tmp_" + api_name_n + "[i], own = true) for i in 1:" +
api_name_nn + "[] ]")
a.fortran_type = "type(c_ptr), intent(out)"
a.fortran_type_post = ("\n type(c_ptr), intent(out) :: " + name +
"_n\n integer(c_size_t) :: " + name +"_nn")
a.fortran_name_post = ",\n & " + name + "_n,\n & " + name + "_nn"
return a
def ovectorvectorsize(name, value=None, python_value=None, julia_value=None):
a = arg(name, value, python_value, julia_value,
"std::vector<std::vector<std::size_t> > &", "size_t **", True)
api_name = "api_" + name + "_"
api_name_n = api_name + "n_"
api_name_nn = api_name + "nn_"
a.c_pre = " std::vector<std::vector<std::size_t> > " + api_name + ";\n"
a.c_arg = api_name
a.c_post = (" vectorvector2ptrptr(" + api_name + ", " + name + ", " +
name + "_n, " + name + "_nn);\n")
a.c = "size_t *** " + name + ", size_t ** " + name + "_n, size_t *" + name + "_nn"
a.cwrap_pre = "size_t **" + api_name + "; size_t *" + api_name_n + ", " + api_name_nn + ";\n"
a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n + ", " + "&" + api_name_nn
a.cwrap_post = (name + ".resize(" + api_name_nn + "); " +
"for(size_t i = 0; i < " + api_name_nn + "; ++i){ " +
name + "[i].assign(" + api_name + "[i], " + api_name +
"[i] + " + api_name_n + "[i]); " + ns + "Free(" +
api_name + "[i]); } " + ns + "Free(" + api_name + "); " +
ns + "Free(" + api_name_n + ");\n")
a.python_pre = (
api_name + ", " + api_name_n + ", " + api_name_nn +
" = POINTER(POINTER(c_size_t))(), POINTER(c_size_t)(), c_size_t()")
a.python_arg = ("byref(" + api_name + "), byref(" + api_name_n +
"), byref(" + api_name_nn + ")")
a.python_return = ("_ovectorvectorsize(" + api_name + ", " + api_name_n +
", " + api_name_nn + ")")
a.julia_ctype = "Ptr{Ptr{Ptr{Csize_t}}}, Ptr{Ptr{Csize_t}}, Ptr{Csize_t}"
a.julia_pre = (api_name + " = Ref{Ptr{Ptr{Csize_t}}}()\n " +
api_name_n + " = Ref{Ptr{Csize_t}}()\n " + api_name_nn +
" = Ref{Csize_t}()")
a.julia_arg = api_name + ", " + api_name_n + ", " + api_name_nn
a.julia_post = ("tmp_" + api_name + " = unsafe_wrap(Array, " + api_name +
"[], " + api_name_nn + "[], own = true)\n " + "tmp_" +
api_name_n + " = unsafe_wrap(Array, " + api_name_n +
"[], " + api_name_nn + "[], own = true)\n " + name +
" = [ unsafe_wrap(Array, tmp_" + api_name + "[i], " +
"tmp_" + api_name_n + "[i], own = true) for i in 1:" +
api_name_nn + "[] ]")
a.fortran_type = "type (c_ptr), intent(out)"
a.fortran_type_post = ("\n type(c_ptr), intent(out) :: " + name +
"_n\n integer(c_size_t) :: " + name +"_nn")
a.fortran_name_post = ",\n & " + name + "_n,\n & " + name + "_nn"
return a
def ovectorvectordouble(name, value=None, python_value=None, julia_value=None):
a = arg(name, value, python_value, julia_value,
"std::vector<std::vector<double> > &", "double **", True)
api_name = "api_" + name + "_"
api_name_n = api_name + "n_"
api_name_nn = api_name + "nn_"
a.c_pre = " std::vector<std::vector<double> > " + api_name + ";\n"
a.c_arg = api_name
a.c_post = (" vectorvector2ptrptr(" + api_name + ", " + name + ", " +
name + "_n, " + name + "_nn);\n")
a.c = "double *** " + name + ", size_t ** " + name + "_n, size_t *" + name + "_nn"
a.cwrap_pre = ("double **" + api_name + "; size_t *" + api_name_n + ", " +
api_name_nn + ";\n")
a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n + ", " + "&" + api_name_nn
a.cwrap_post = (name + ".resize(" + api_name_nn + "); " +
"for(size_t i = 0; i < " + api_name_nn + "; ++i){ " +
name + "[i].assign(" + api_name + "[i], " + api_name +
"[i] + " + api_name_n + "[i]); " + ns + "Free(" +
api_name + "[i]); } " + ns + "Free(" + api_name + "); " +
ns + "Free(" + api_name_n + ");\n")
a.python_pre = (
api_name + ", " + api_name_n + ", " + api_name_nn +
" = POINTER(POINTER(c_double))(), POINTER(c_size_t)(), c_size_t()")
a.python_arg = ("byref(" + api_name + "), byref(" + api_name_n +
"), byref(" + api_name_nn + ")")
a.python_return = ("_ovectorvectordouble(" + api_name + ", " + api_name_n +
", " + api_name_nn + ")")
a.julia_ctype = "Ptr{Ptr{Ptr{Cdouble}}}, Ptr{Ptr{Csize_t}}, Ptr{Csize_t}"
a.julia_pre = (api_name + " = Ref{Ptr{Ptr{Cdouble}}}()\n " +
api_name_n + " = Ref{Ptr{Csize_t}}()\n " + api_name_nn +
" = Ref{Csize_t}()")
a.julia_arg = api_name + ", " + api_name_n + ", " + api_name_nn
a.julia_post = ("tmp_" + api_name + " = unsafe_wrap(Array, " + api_name +
"[], " + api_name_nn + "[], own = true)\n " + "tmp_" +
api_name_n + " = unsafe_wrap(Array, " + api_name_n +
"[], " + api_name_nn + "[], own = true)\n " + name +
" = [ unsafe_wrap(Array, tmp_" + api_name + "[i], " +
"tmp_" + api_name_n + "[i], own = true) for i in 1:" +
api_name_nn + "[] ]")
a.fortran_type = "type (c_ptr), intent(out)"
a.fortran_type_post = ("\n type(c_ptr), intent(out) :: " + name +
"_n\n integer (c_size_t) :: " + name + "_nn")
a.fortran_name_post = ",\n & " + name + "_n,\n & " + name + "_nn"
return a
def ovectorvectorpair(name, value=None, python_value=None, julia_value=None):
a = arg(name, value, python_value, julia_value,
"std::vector<" + ns + "::vectorpair> &", "int **", True)
api_name = "api_" + name + "_"
api_name_n = api_name + "n_"
api_name_nn = api_name + "nn_"
a.c_pre = " std::vector<" + ns + "::vectorpair >" + api_name + ";\n"
a.c_arg = api_name
a.c_post = (" vectorvectorpair2intptrptr(" + api_name + ", " + name +
", " + name + "_n, " + name + "_nn);\n")
a.c = "int *** " + name + ", size_t ** " + name + "_n, size_t *" + name + "_nn"
a.cwrap_pre = "int **" + api_name + "; size_t *" + api_name_n + ", " + api_name_nn + ";\n"
a.cwrap_arg = "&" + api_name + ", " + "&" + api_name_n + ", " + "&" + api_name_nn
a.cwrap_post = (name + ".resize(" + api_name_nn + "); " +
"for(size_t i = 0; i < " + api_name_nn + "; ++i){ " +
name + "[i].resize(" + api_name_n + "[i] / 2); " +
"for(size_t j = 0; j < " + api_name_n + "[i] / 2; ++j){ " +
name + "[i][j].first = " + api_name + "[i][j * 2 + 0]; " +
name + "[i][j].second = " + api_name +
"[i][j * 2 + 1]; } " + ns + "Free(" + api_name +
"[i]); } " + ns + "Free(" + api_name + "); " + ns +
"Free(" + api_name_n + ");\n")
a.python_pre = (
api_name + ", " + api_name_n + ", " + api_name_nn +
" = POINTER(POINTER(c_int))(), POINTER(c_size_t)(), c_size_t()")
a.python_arg = ("byref(" + api_name + "), byref(" + api_name_n +
"), byref(" + api_name_nn + ")")
a.python_return = ("_ovectorvectorpair(" + api_name + ", " + api_name_n +
", " + api_name_nn + ")")
a.julia_ctype = "Ptr{Ptr{Ptr{Cint}}}, Ptr{Ptr{Csize_t}}, Ptr{Csize_t}"
a.julia_pre = (api_name + " = Ref{Ptr{Ptr{Cint}}}()\n " + api_name_n +
" = Ref{Ptr{Csize_t}}()\n " + api_name_nn +
" = Ref{Csize_t}()")
a.julia_arg = api_name + ", " + api_name_n + ", " + api_name_nn
a.julia_post = (
"tmp_" + api_name + " = unsafe_wrap(Array, " + api_name + "[], " +
api_name_nn + "[], own = true)\n " + "tmp_" + api_name_n +
" = unsafe_wrap(Array, " + api_name_n + "[], " + api_name_nn +
"[], own = true)\n " + name + " = Vector{Tuple{Cint,Cint}}[]\n " +
"resize!(" + name + ", " + api_name_nn + "[])\n " + "for i in 1:" +
api_name_nn + "[]\n " + " tmp = unsafe_wrap(Array, tmp_" +
api_name + "[i], tmp_" + api_name_n + "[i], own = true)\n " + " " +
name + "[i] = [(tmp[i], tmp[i+1]) for i in 1:2:length(tmp)]\n " +
"end")
a.fortran_type = "type (C_PTR), intent(out)"
a.fortran_type_post = ("\n type(c_ptr), intent(out) :: " + name +
"_n\n integer (C_SIZE_T) ::" + name +"_nn")
a.fortran_name_post = ",\n & " + name + "_n,\n & " + name + "_nn"
return a
# special types
def iargcargv():
a = arg("", None, None, None, "", "", False)
a.cpp = "int argc = 0, char ** argv = 0"
a.c_arg = "argc, argv"
a.c = "int argc, char ** argv"
a.c_pre = ""
a.c_post = ""
a.cwrap_arg = "argc, argv"
a.name = "argv"
a.python_value = "[]"
a.julia_value = "Vector{String}()"
a.python_arg = "api_argc_, api_argv_"
a.python_pre = "api_argc_, api_argv_ = _iargcargv(argv)"
a.julia_ctype = "Cint, Ptr{Ptr{Cchar}}"
a.julia_arg = "length(argv), argv"
a.texi = "(argc = 0)}, @code{argv = []"
a.fortran_name_pre = "argc,\n & "
a.fortran_type = "integer (C_INT), value :: argc\n type (C_PTR)"
a.fortran_type_post = "(*)"
return a
def isizefun(name):
a = arg(name, None, None, None, "", "", False)
a.cpp = "std::function<double(int, int, double, double, double, double)> " + name
a.c_arg = ("std::bind(" + name + ", std::placeholders::_1, " +
"std::placeholders::_2, std::placeholders::_3, " +
"std::placeholders::_4, std::placeholders::_5, " +
"std::placeholders::_6, " + name + "_data)")
a.c = ("double (*" + name + ")" +
"(int dim, int tag, double x, double y, double z, double lc, void * data), " +
"void * " + name + "_data")
a.cwrap_pre = "struct " + name + """_caller_ {
static double call(int dim, int tag, double x, double y, double z, double lc, void * callbackp_) {
return (*static_cast<std::function<double(int, int, double, double, double, double)>*> (callbackp_))(dim, tag, x, y, z, lc);
}
};
// FIXME memory leak
auto *""" + name + "_ptr_ = new std::function<double(int, int, double, double, double, double)>(" + name + """);
"""
a.cwrap_arg = "&" + name + "_caller_::call, " + name + "_ptr_"
a.python_pre = (
"global api_" + name + "_type_\n" + " api_" + name +
"_type_ = " +
"CFUNCTYPE(c_double, c_int, c_int, c_double, c_double, c_double, c_double, c_void_p)\n"
+ " global api_" + name + "_\n" + " api_" +
name + "_ = api_" + name + "_type_(lambda dim, tag, x, y, z, lc, _ : " +
name + "(dim, tag, x, y, z, lc))")
a.python_arg = "api_" + name + "_, None"
a.julia_pre = (
"api_" + name + "__(dim, tag, x, y, z, lc, data) = " + name +
"(dim, tag, x, y, z, lc)\n " + "api_" + name + "_ = @cfunction($api_" +
name + "__" +
", Cdouble, (Cint, Cint, Cdouble, Cdouble, Cdouble, Cdouble, Ptr{Cvoid}))")
a.julia_arg = "api_" + name + "_, C_NULL"
a.julia_ctype = "Ptr{Cvoid}, Ptr{Cvoid}"
a.fortran_type = "type (C_FUNPTR)"
a.fortran_type_post = " ! to do "
return a
class Module:
def __init__(self, name, doc):
self.name = name
self.doc = doc
self.fs = []
self.submodules = []
def add(self, name, doc, rtype, *args):
self.fs.append((rtype, name, args, doc, []))
def add_special(self, name, doc, special, rtype, *args):
self.fs.append((rtype, name, args, doc, special))
def add_module(self, name, doc):
module = Module(name, doc)
self.submodules.append(module)
return module
cpp_header = """// {0}
//
// See the LICENSE.txt file in the {3} root directory for license information.
// Please report all issues on {1}
#ifndef {2}_H
#define {2}_H
// This file defines the {3} C++ API (v{4}.{5}.{6}).
//
// Do not edit this file directly: it is automatically generated by `api/gen.py'.
//
// By design, the {3} C++ API is purely functional, and only uses elementary
// types from the C++ standard library. See `tutorials/c++' and `examples/api'
// for tutorials and examples.
#include <cmath>
#include <vector>
#include <string>
#include <utility>
#include <functional>
#define {2}_API_VERSION "{4}.{5}.{6}"
#define {2}_API_VERSION_MAJOR {4}
#define {2}_API_VERSION_MINOR {5}
#define {2}_API_VERSION_PATCH {6}
#if defined({2}_DLL)
#if defined({2}_DLL_EXPORT)
#define {2}_API __declspec(dllexport)
#else
#define {2}_API __declspec(dllimport)
#endif
#elif defined(__GNUC__)
#define {2}_API __attribute__ ((visibility("default")))
#else
#define {2}_API
#endif
#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif
namespace {7} {{
// A geometrical entity in the {3} API is represented by two integers: its
// dimension (dim = 0, 1, 2 or 3) and its tag (its unique, strictly positive
// identifier). When dealing with multiple geometrical entities of possibly
// different dimensions, the entities are packed as a vector of (dim, tag)
// integer pairs.
typedef std::vector<std::pair<int, int> > vectorpair;
}}
"""
cpp_footer = """#endif
"""
c_header = """/*
* {0}
*
* See the LICENSE.txt file in the {3} root directory for license information.
* Please report all issues on {1}
*/
#ifndef {2}C_H
#define {2}C_H
/*
* This file defines the {3} C API (v{4}.{5}.{6}).
*
* Do not edit this file directly: it is automatically generated by `api/gen.py'.
*
* By design, the {3} C API is purely functional, and only uses elementary
* C types. See `tutorials/c' and `examples/api' for tutorials and examples.
*/
#include <stddef.h>
#define {2}_API_VERSION "{4}.{5}.{6}"
#define {2}_API_VERSION_MAJOR {4}
#define {2}_API_VERSION_MINOR {5}
#define {2}_API_VERSION_PATCH {6}
#if defined({2}_DLL)
#if defined({2}_DLL_EXPORT)
#define {2}_API __declspec(dllexport)
#else
#define {2}_API __declspec(dllimport)
#endif
#elif defined(__GNUC__)
#define {2}_API __attribute__ ((visibility("default")))
#else
#define {2}_API
#endif
/* All the functions in the {3} C API that return arrays allocate the
* necessary memory with {7}Malloc(). These arrays should be deallocated
* with {7}Free(). */
{2}_API void {7}Free(void *p);
{2}_API void *{7}Malloc(size_t n);
"""
c_footer = """
#endif
"""
c_cpp_header = """// {0}
//
// See the LICENSE.txt file in the {4} root directory for license information.
// Please report all issues on {1}
#include <string.h>
#include <stdlib.h>
#include "{2}.h"
extern \"C\" {{
#include "{2}c.h"
}}
{3}_API void *{2}Malloc(size_t n)
{{
return malloc(n);
}}
{3}_API void {2}Free(void *p)
{{
if(p) free(p);
}}
"""
c_cpp_utils = """
void vectorvectorpair2intptrptr(const std::vector<{0}::vectorpair > &v, int ***p, size_t **size, size_t *sizeSize)
{{
*p = (int**){0}Malloc(sizeof(int*) * v.size());
*size = (size_t*){0}Malloc(sizeof(size_t) * v.size());
for(size_t i = 0; i < v.size(); ++i)
vectorpair2intptr(v[i], &(*p)[i], &((*size)[i]));
*sizeSize = v.size();
}}
"""
cwrap_header = """// {0}
//
// See the LICENSE.txt file in the {3} root directory for license information.
// Please report all issues on {1}
#ifndef {2}_H
#define {2}_H
// This file redefines the {3} C++ API in terms of the C API (v{4}.{5}.{6}).
//
// This is provided as a convenience for users of the binary {3} SDK whose C++
// compiler ABI is not compatible with the ABI of the C++ compiler used to create
// the SDK (and who can thus not directly use the C++ API defined in `{7}.h').
//
// To use this header file in your C++ code, simply rename it as `{7}.h'.
//
// Note that using this header file will lead to (slightly) reduced performance
// compared to using the native {3} C++ API from the original `{7}.h', as it
// entails additional data copies between this C++ wrapper, the C API and the
// native C++ code.
//
// Do not edit this file directly: it is automatically generated by `api/gen.py'.
#include <cmath>
#include <vector>
#include <string>
#include <utility>
#include <functional>
#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif
extern \"C\" {{
#include "{7}c.h"
}}
namespace {7} {{
// A geometrical entity in the {3} API is represented by two integers: its
// dimension (dim = 0, 1, 2 or 3) and its tag (its unique, strictly positive
// identifier). When dealing with multiple geometrical entities of possibly
// different dimensions, the entities are packed as a vector of (dim, tag)
// integer pairs.
typedef std::vector<std::pair<int, int> > vectorpair;
}}
"""
cwrap_utils = """
template<typename t>
{1}void vector2ptr(const std::vector<t> &v, t **p, size_t *size)
{{
*p = (t*){0}Malloc(sizeof(t) * v.size());
for(size_t i = 0; i < v.size(); ++i){{
(*p)[i] = v[i];
}}
*size = v.size();
}}
{1}void vectorpair2intptr(const {0}::vectorpair &v, int **p, size_t *size)
{{
*p = (int*){0}Malloc(sizeof(int) * v.size() * 2);
for(size_t i = 0; i < v.size(); ++i){{
(*p)[i * 2 + 0] = v[i].first;
(*p)[i * 2 + 1] = v[i].second;
}}
*size = v.size() * 2;
}}
{1}void vectorstring2charptrptr(const std::vector<std::string> &v, char ***p, size_t *size)
{{
*p = (char**){0}Malloc(sizeof(char*) * v.size());
for(size_t i = 0; i < v.size(); ++i){{
(*p)[i] = (char*){0}Malloc(sizeof(char) * (v[i].size() + 1));
for(size_t j = 0; j < v[i].size(); j++) (*p)[i][j] = v[i][j];
(*p)[i][v[i].size()] = '\\0';
}}
*size = v.size();
}}
template<typename t>
{1}void vectorvector2ptrptr(const std::vector<std::vector<t> > &v, t ***p, size_t **size, size_t *sizeSize)
{{
*p = (t**){0}Malloc(sizeof(t*) * v.size());
*size = (size_t*){0}Malloc(sizeof(size_t) * v.size());
for(size_t i = 0; i < v.size(); ++i)
vector2ptr(v[i], &((*p)[i]), &((*size)[i]));
*sizeSize = v.size();
}}
"""
cwrap_footer = """#endif
"""
python_header = """# {0}
#
# See the LICENSE.txt file in the {2} root directory for license information.
# Please report all issues on {1}
# This file defines the {2} Python API (v{3}.{4}.{5}).
#
# Do not edit this file directly: it is automatically generated by `api/gen.py'.
#
# By design, the {2} Python API is purely functional, and only uses elementary
# Python types (as well as `numpy' arrays if `numpy' is available). See
# `tutorials/python' and `examples/api' for tutorials and examples.
from ctypes import *
from ctypes.util import find_library
import signal
import os
import platform
from math import pi
{6}_API_VERSION = "{3}.{4}.{5}"
{6}_API_VERSION_MAJOR = {3}
{6}_API_VERSION_MINOR = {4}
{6}_API_VERSION_PATCH = {5}
__version__ = {6}_API_VERSION
oldsig = signal.signal(signal.SIGINT, signal.SIG_DFL)
moduledir = os.path.dirname(os.path.realpath(__file__))
if platform.system() == "Windows":
libname = "{7}-{3}.{4}.dll"
libdir = os.path.dirname(moduledir)
elif platform.system() == "Darwin":
libname = "lib{7}.{3}.{4}.dylib"
libdir = os.path.dirname(os.path.dirname(moduledir))
else:
libname = "lib{7}.so.{3}.{4}"
libdir = os.path.dirname(os.path.dirname(moduledir))
libpath = os.path.join(libdir, libname)
if not os.path.exists(libpath):
libpath = os.path.join(libdir, "Lib", libname)
if not os.path.exists(libpath):
libpath = os.path.join(moduledir, libname)
if not os.path.exists(libpath):
if platform.system() == "Windows":
libpath = find_library("{7}-{3}.{4}")
if not libpath:
libpath = find_library("{7}")
else:
libpath = find_library("{7}")
lib = CDLL(libpath)
try_numpy = True # set this to False to never use numpy
use_numpy = False
if try_numpy:
try:
import numpy
try:
from weakref import finalize as weakreffinalize
except:
from backports.weakref import finalize as weakreffinalize
use_numpy = True
except:
pass
# Utility functions, not part of the Gmsh Python API
def _ostring(s):
sp = s.value.decode("utf-8")
lib.{7}Free(s)
return sp
def _ovectorpair(ptr, size):
v = list((ptr[i * 2], ptr[i * 2 + 1]) for i in range(size//2))
lib.{7}Free(ptr)
return v
def _ovectorint(ptr, size):
if use_numpy:
if size == 0 :
lib.{7}Free(ptr)
return numpy.ndarray((0,),numpy.int32)
v = numpy.ctypeslib.as_array(ptr, (size, ))
weakreffinalize(v, lib.{7}Free, ptr)
else:
v = list(ptr[i] for i in range(size))
lib.{7}Free(ptr)
return v
def _ovectorsize(ptr, size):
if use_numpy:
if size == 0 :
lib.{7}Free(ptr)
return numpy.ndarray((0,),numpy.uintp)
v = numpy.ctypeslib.as_array(ptr, (size, ))
weakreffinalize(v, lib.{7}Free, ptr)
else:
v = list(ptr[i] for i in range(size))
lib.{7}Free(ptr)
return v
def _ovectordouble(ptr, size):
if use_numpy:
if size == 0 :
lib.{7}Free(ptr)
return numpy.ndarray((0,),numpy.float64)
v = numpy.ctypeslib.as_array(ptr, (size, ))
weakreffinalize(v, lib.{7}Free, ptr)
else:
v = list(ptr[i] for i in range(size))
lib.{7}Free(ptr)
return v
def _ovectorstring(ptr, size):
v = list(_ostring(cast(ptr[i], c_char_p)) for i in range(size))
lib.{7}Free(ptr)
return v
def _ovectorvectorint(ptr, size, n):
v = [_ovectorint(pointer(ptr[i].contents), size[i]) for i in range(n.value)]
lib.{7}Free(size)
lib.{7}Free(ptr)
return v
def _ovectorvectorsize(ptr, size, n):
v = [_ovectorsize(pointer(ptr[i].contents), size[i]) for i in range(n.value)]
lib.{7}Free(size)
lib.{7}Free(ptr)
return v
def _ovectorvectordouble(ptr, size, n):
v = [_ovectordouble(pointer(ptr[i].contents), size[i]) for i in range(n.value)]
lib.{7}Free(size)
lib.{7}Free(ptr)
return v
def _ovectorvectorpair(ptr, size, n):
v = [_ovectorpair(pointer(ptr[i].contents), size[i]) for i in range(n.value)]
lib.{7}Free(size)
lib.{7}Free(ptr)
return v
def _ivectorint(o):
if use_numpy:
array = numpy.ascontiguousarray(o, numpy.int32)
if(len(o) and array.ndim != 1):
raise Exception("Invalid data for input vector of integers")
ct = array.ctypes
ct.array = array
return ct, c_size_t(len(o))
else:
return (c_int * len(o))(*o), c_size_t(len(o))
def _ivectorsize(o):
if use_numpy:
array = numpy.ascontiguousarray(o, numpy.uintp)
if(len(o) and array.ndim != 1):
raise Exception("Invalid data for input vector of sizes")
ct = array.ctypes
ct.array = array
return ct, c_size_t(len(o))
else:
return (c_size_t * len(o))(*o), c_size_t(len(o))
def _ivectordouble(o):
if use_numpy:
array = numpy.ascontiguousarray(o, numpy.float64)
if(len(o) and array.ndim != 1):
raise Exception("Invalid data for input vector of doubles")
ct = array.ctypes
ct.array = array
return ct, c_size_t(len(o))
else:
return (c_double * len(o))(*o), c_size_t(len(o))
def _ivectorpair(o):
if use_numpy:
array = numpy.ascontiguousarray(o, numpy.int32)
if(len(o) and (array.ndim != 2 or array.shape[1] != 2)):
raise Exception("Invalid data for input vector of pairs")
ct = array.ctypes
ct.array = array
return ct, c_size_t(len(o) * 2)
else:
if(len(o) and len(o[0]) != 2):
raise Exception("Invalid data for input vector of pairs")
return ((c_int * 2) * len(o))(*o), c_size_t(len(o) * 2)
def _ivectorstring(o):
return (c_char_p * len(o))(*(s.encode() for s in o)), c_size_t(len(o))
def _ivectorvectorint(os):
n = len(os)
parrays = [_ivectorint(o) for o in os]
sizes = (c_size_t * n)(*(a[1] for a in parrays))
arrays = (POINTER(c_int) * n)(*(cast(a[0], POINTER(c_int)) for a in parrays))
arrays.ref = [a[0] for a in parrays]
size = c_size_t(n)
return arrays, sizes, size
def _ivectorvectorsize(os):
n = len(os)
parrays = [_ivectorsize(o) for o in os]
sizes = (c_size_t * n)(*(a[1] for a in parrays))
arrays = (POINTER(c_size_t) * n)(*(cast(a[0], POINTER(c_size_t)) for a in parrays))
arrays.ref = [a[0] for a in parrays]
size = c_size_t(n)
return arrays, sizes, size
def _ivectorvectordouble(os):
n = len(os)
parrays = [_ivectordouble(o) for o in os]
sizes = (c_size_t * n)(*(a[1] for a in parrays))
arrays = (POINTER(c_double) * n)(*(cast(a[0], POINTER(c_double)) for a in parrays))
arrays.ref = [a[0] for a in parrays]
size = c_size_t(n)
return arrays, sizes, size
def _iargcargv(o):
return c_int(len(o)), (c_char_p * len(o))(*(s.encode() for s in o))
# Gmsh Python API begins here
"""
julia_header = """# {0}
#
# See the LICENSE.txt file in the {2} root directory for license information.
# Please report all issues on {1}
# This file defines the {2} Julia API (v{3}.{4}.{5}).
#
# Do not edit this file directly: it is automatically generated by `api/gen.py'.
#
# By design, the {2} Julia API is purely functional, and only uses elementary
# Julia types. See `tutorials/julia' and `examples/api' for tutorials and
# examples.
"""
fortran_header = """c
c {0}
c
c See the LICENSE.txt file in the {3} root directory for license information.
c Please report all issues on {1}
c
!DEC$ IF DEFINED ({2}F_H)
!DEC$ ELSE
!DEC$ DEFINE {2}F_H
c
c This file defines the {3} Fortran API (v{4}.{5}.{6}).
c
c Do not edit this file directly: it is automatically generated by `api/gen.py'.
c
c By design, the {3} Fortran API is purely functional, and only uses elementary
c Fortran types. See `tutorials/fortran' and `examples/api' for tutorials and
c examples.
c
!DEC$ DEFINE {2}_API_VERSION_MAJOR = {4}
!DEC$ DEFINE {2}_API_VERSION_MINOR = {5}
!DEC$ DEFINE {2}_API_VERSION_PATCH = {6}
module gmsh_fortran
use, intrinsic :: iso_c_binding
character(len = 5), parameter :: {2}_API_VERSION = "{4}.{5}.{6}"
real(c_double), parameter::M_PI = 3.14159265358979323846d0
interface
"""
fortran_footer = """
end interface
end module gmsh_fortran
!DEC$ ENDIF
"""
def capi(s):
return s[:1].upper() + s[1:]
class API:
def __init__(
self,
version_major,
version_minor,
version_patch,
namespace = "gmsh",
code = "Gmsh",
copyright = "Gmsh - Copyright (C) 1997-2022 C. Geuzaine, J.-F. Remacle",
issues = "https://gitlab.onelab.info/gmsh/gmsh/issues."):
self.version_major = version_major
self.version_minor = version_minor
self.version_patch = version_patch
global ns
ns = namespace
self.code = code
self.copyright = copyright
self.issues = issues
self.modules = []
self.api_lineno = {'cpp': {}, 'c': {}, 'py': {}, 'jl': {}, 'f': {}}
def add_module(self, name, doc):
module = Module(name, doc)
self.modules.append(module)
return module
def fwrite(self, f, s):
self.current_lineno += s.count('\n')
f.write(s)
def flog(self, lang, fname):
self.api_lineno[lang][fname] = self.current_lineno
def write_cpp(self):
def write_module(module, indent, cpp_mpath):
cpp_mpath += module.name + "::"
self.fwrite(
f, indent + "namespace " + module.name + " { // " +
capi(module.doc) + "\n\n")
indent += " "
for rtype, name, args, doc, special in module.fs:
rt = rtype.rcpp_type if rtype else "void"
self.fwrite(
f,
indent + "// " + cpp_mpath + name + "\n" + indent + "//\n")
self.fwrite(
f, indent + "// " + ("\n" + indent + "// ").join(
textwrap.wrap(doc, 80 - len(indent))) + "\n")
fnameapi = indent + ns.upper(
) + "_API " + rt + " " + name + "("
self.flog('cpp', cpp_mpath.replace('::', '/') + name)
self.fwrite(f, fnameapi)
if args:
self.fwrite(f, (",\n" + ' ' * len(fnameapi)).join(
a.cpp for a in args))
self.fwrite(f, ");\n\n")
for m in module.submodules:
write_module(m, indent, cpp_mpath)
self.fwrite(f,
indent[:-2] + "} // namespace " + module.name + "\n\n")
self.current_lineno = 1
with open(ns + ".h", "w") as f:
self.fwrite(
f,
cpp_header.format(self.copyright, self.issues, ns.upper(),
self.code, self.version_major,
self.version_minor, self.version_patch, ns))
for m in self.modules:
write_module(m, "", "")
self.fwrite(f, cpp_footer)
def write_c(self):
def write_module(module, c_namespace, cpp_namespace, indent):
cpp_namespace += module.name + "::"
if c_namespace:
c_namespace += module.name[0].upper() + module.name[1:]
else:
c_namespace = module.name
fcwrap.write(indent + "namespace " + module.name + " { // " +
capi(module.doc) + "\n\n")
indent += " "
for rtype, name, args, doc, special in module.fs:
# *c.h
fname = c_namespace + name[0].upper() + name[1:]
self.fwrite(
f,
"\n/* " + "\n * ".join(textwrap.wrap(doc, 75)) + " */\n")
fnameapi = ns.upper() + "_API " + (rtype.rc_type if rtype else
"void") + " " + fname + "("
self.flog('c', cpp_namespace.replace('::', '/') + name)
self.fwrite(
f, fnameapi + (",\n" + ' ' * len(fnameapi)).join(
list((a.c for a in args + (oint("ierr"), )))) + ");\n")
if "rawc" not in special:
# *c.cpp
fc.write(ns.upper() + "_API " +
(rtype.rc_type if rtype else "void"))
fc.write(
" " + fname + "(" +
", ".join(list((a.c for a in args +
(oint("ierr"), )))) + ")\n{\n")
if rtype:
fc.write(" " + rtype.rc_type + " result_api_ = 0;\n")
fc.write(" if(ierr) *ierr = 0;\n")
fc.write(" try {\n")
fc.write("".join((a.c_pre for a in args)))
fc.write(" ")
if rtype:
fc.write("result_api_ = ")
fc.write(cpp_namespace + name + "(" +
", ".join(list((a.c_arg for a in args))) + ");\n")
fc.write("".join((a.c_post for a in args)))
fc.write(" }\n catch(...){\n " +
"if(ierr) *ierr = 1;\n }\n")
if rtype:
fc.write(" return result_api_;\n")
fc.write("}\n\n")
# *.h_cwrap
fcwrap.write(indent + "// " +
("\n" + indent +
"// ").join(textwrap.wrap(doc, 80 -
len(indent))) + "\n")
rt = rtype.rcpp_type if rtype else "void"
fnameapi = indent + "inline " + rt + " " + name + "("
fcwrap.write(fnameapi)
if args:
fcwrap.write(
(",\n" + ' ' * len(fnameapi)).join(a.cpp
for a in args))
fcwrap.write(")\n" + indent + "{\n" + indent +
" int ierr = 0;\n")
for a in args:
if a.cwrap_pre:
fcwrap.write(indent + " " + a.cwrap_pre)
fcwrap.write(indent + " ")
if rtype:
fcwrap.write(rt + " result_api_ = ")
fcwrap.write(fname + "(" + ", ".join((a.cwrap_arg
for a in args)))
if args:
fcwrap.write(", &ierr);\n")
else:
fcwrap.write("&ierr);\n")
if name == 'getLastError': # special case for getLastError() function
fcwrap.write(
indent + " " +
'if(ierr) throw "Could not get last error";\n')
else:
fcwrap.write(indent + " " +
"if(ierr) throwLastError();\n")
for a in args:
if a.cwrap_post:
fcwrap.write(indent + " " + a.cwrap_post)
if rtype:
fcwrap.write(indent + " " + "return result_api_;\n")
fcwrap.write(indent + "}\n\n")
for m in module.submodules:
write_module(m, c_namespace, cpp_namespace, indent)
fcwrap.write(indent[:-2] + "} // namespace " + module.name +
"\n\n")
self.current_lineno = 1
with open(ns + "c.h", "w") as f:
with open(ns + "c.cpp", "w") as fc:
with open(ns + ".h_cwrap", "w") as fcwrap:
self.fwrite(
f,
c_header.format(self.copyright, self.issues,
ns.upper(), self.code,
self.version_major, self.version_minor,
self.version_patch, ns))
fc.write(
c_cpp_header.format(self.copyright, self.issues, ns,
ns.upper(), self.code))
fc.write(cwrap_utils.format(ns, ""))
fc.write(c_cpp_utils.format(ns))
fc.write("\n")
fcwrap.write(
cwrap_header.format(self.copyright, self.issues,
ns.upper(), self.code,
self.version_major,
self.version_minor,
self.version_patch, ns))
fcwrap.write("namespace " + ns + " {\n")
s = cwrap_utils.format(ns, "inline ").split('\n')
for line in s:
fcwrap.write(" " + line + "\n")
fcwrap.write(" inline void throwLastError()\n")
fcwrap.write(" {\n")
fcwrap.write(' int ierr = 0;\n')
fcwrap.write(' char *api_error_;\n')
fcwrap.write(
' gmshLoggerGetLastError(&api_error_, &ierr);\n')
fcwrap.write(
' if(ierr) throw "Could not get last error";\n')
fcwrap.write(
' std::string error = std::string(api_error_);\n')
fcwrap.write(' gmshFree(api_error_);\n')
fcwrap.write(' throw error;\n')
fcwrap.write(" }\n\n")
fcwrap.write("}\n\n")
for module in self.modules:
write_module(module, "", "", "")
self.fwrite(f, c_footer)
fcwrap.write(cwrap_footer)
def write_python(self):
def parg(a):
return a.name + (("=" + a.python_value) if a.python_value else "")
def write_function(f, fun, c_mpath, py_mpath, indent):
(rtype, name, args, doc, special) = fun
if "onlycc++" in special: return
if "nopython" in special: return
iargs = list(a for a in args if not a.out)
oargs = list(a for a in args if a.out)
self.fwrite(f, "\n")
if c_mpath != ns:
self.fwrite(f, indent + "@staticmethod\n")
self.flog('py', py_mpath.replace('.', '/') + name)
self.fwrite(
f, indent + "def " + name + "(" + ", ".join(
(parg(a) for a in iargs)) + "):\n")
ind = indent + " "
self.fwrite(f, ind + '"""\n')
self.fwrite(
f, ind + py_mpath + name + "(" +
", ".join(parg(a) for a in iargs) + ")\n\n")
self.fwrite(
f,
ind + ("\n" + ind).join(textwrap.wrap(doc, 75)) + "\n")
if rtype or oargs:
self.fwrite(
f, "\n" + ind + "Return " +
", ".join(([("an " if rtype.rtexi_type ==
"integer value" else "a ") +
rtype.rtexi_type] if rtype else []) +
[("`" + a.name + "'") for a in oargs]) + ".\n")
self.fwrite(f, ind + '"""\n')
for a in args:
if a.python_pre: self.fwrite(f, ind + a.python_pre + "\n")
self.fwrite(f, ind + "ierr = c_int()\n")
c_name = c_mpath + name[0].upper() + name[1:]
if rtype is odouble:
self.fwrite(f, ind + "lib." + c_name + ".restype = c_double\n")
self.fwrite(
f, ind + "api_result_ = " if
((rtype is oint) or (rtype is odouble)) else (ind))
self.fwrite(
f, "lib." + c_name + "(\n " + ind +
(",\n" + ind + " ").join(
tuple((a.python_arg
for a in args)) + ("byref(ierr)", )) + ")\n")
if name == "finalize": # special case for finalize() function
self.fwrite(f, ind + "if oldsig is not None:\n")
self.fwrite(
f, ind + " signal.signal(signal.SIGINT, oldsig)\n")
self.fwrite(f, ind + "if ierr.value != 0:\n")
if name == "getLastError": # special case for getLastError() function
self.fwrite(
f, ind +
" raise Exception('Could not get last error')\n")
else:
self.fwrite(
f, ind + " raise Exception(logger.getLastError())\n")
r = (["api_result_"]) if rtype else []
r += list((o.python_return for o in oargs))
if len(r) != 0:
if len(r) == 1:
self.fwrite(f, ind + "return " + r[0] + "\n")
else:
self.fwrite(
f, ind + "return (\n" + ind + " " +
(",\n" + ind + " ").join(r) + ")\n")
# define alias with underscore (standard python style)
name_ = re.sub('([A-Z]+)', r'_\1', name).lower()
if name != name_:
self.fwrite(f, indent + name_ + " = " + name + "\n")
def write_module(f, m, c_mpath, py_mpath, indent):
if c_mpath:
c_mpath += m.name[0].upper() + m.name[1:]
py_mpath += m.name + "."
else:
c_mpath = m.name
py_mpath = m.name + "."
for fun in m.fs:
write_function(f, fun, c_mpath, py_mpath, indent)
for module in m.submodules:
self.fwrite(f,
"\n\n" + indent + "class " + module.name + ":\n")
indentm = indent + " "
self.fwrite(f, indentm + '"""\n')
self.fwrite(
f, indentm + ("\n" + indentm).join(
textwrap.wrap(capi(module.doc), 75)) + "\n")
self.fwrite(f, indentm + '"""\n')
write_module(f, module, c_mpath, py_mpath, indentm)
self.current_lineno = 1
with open(ns + ".py", "w") as f:
self.fwrite(
f,
python_header.format(self.copyright, self.issues, self.code,
self.version_major, self.version_minor,
self.version_patch, ns.upper(), ns))
for module in self.modules:
write_module(f, module, "", "", "")
def write_julia(self):
def parg(a):
return a.name + ((" = " + a.julia_value) if a.julia_value else "")
def write_function(f, fun, c_mpath, jl_mpath):
(rtype, name, args, doc, special) = fun
if "onlycc++" in special: return
if "nojulia" in special: return
iargs = list(a for a in args if not a.out)
oargs = list(a for a in args if a.out)
self.fwrite(f, '\n"""\n ')
self.fwrite(
f, jl_mpath + name + "(" + ", ".join(parg(a)
for a in iargs) + ")\n\n")
self.fwrite(
f, "\n".join(textwrap.wrap(doc, 80)).replace("'", "`") + "\n")
if rtype or oargs:
self.fwrite(
f, "\nReturn " +
", ".join(([("an " if rtype.rtexi_type ==
"integer value" else "a ") +
rtype.rtexi_type] if rtype else []) +
[("`" + a.name + "`") for a in oargs]) + ".\n")
self.fwrite(f, '"""\n')
self.flog('jl', jl_mpath.replace('.', '/') + name)
self.fwrite(
f, "function " + name + "(" + ", ".join(
(parg(a) for a in iargs)) + ")\n")
for a in args:
if a.julia_pre: self.fwrite(f, " " + a.julia_pre + "\n")
self.fwrite(f, " ierr = Ref{Cint}()\n ")
self.fwrite(
f, "api_result_ = " if
((rtype is oint) or (rtype is odouble)) else "")
c_name = c_mpath + name[0].upper() + name[1:]
self.fwrite(
f, "ccall((:" + c_name + ", " +
("" if c_mpath == ns else ns + ".") + "lib), " +
("Cvoid" if rtype is None else rtype.rjulia_type) + ",\n" +
" " * 10 + "(" + ", ".join(
(tuple(a.julia_ctype for a in args) + ("Ptr{Cint}", ))) +
("," if not len(args) else "") + "),\n" + " " * 10 +
", ".join(tuple(a.julia_arg
for a in args) + ("ierr", )) + ")\n")
if name == "getLastError": # special case for getLastError() function
self.fwrite(
f,
' ierr[] != 0 && error("Could not get last error")\n')
else:
self.fwrite(
f,
' ierr[] != 0 && error(gmsh.logger.getLastError())\n')
for a in args:
if a.julia_post: self.fwrite(f, " " + a.julia_post + "\n")
r = (["api_result_"]) if rtype else []
r += list((o.julia_return for o in oargs))
self.fwrite(f, " return ")
if len(r) == 0:
self.fwrite(f, "nothing")
else:
self.fwrite(f, ", ".join(r))
self.fwrite(f, "\nend\n")
# define alias with underscore (closer to Julia style)
name_ = re.sub('([A-Z]+)', r'_\1', name).lower()
if name != name_:
self.fwrite(f, "const " + name_ + " = " + name + "\n")
def write_module(f, m, c_mpath, jl_mpath, level):
self.fwrite(f, '\n"""\n ')
self.fwrite(f, "module " + jl_mpath + m.name + "\n\n")
self.fwrite(f, "\n".join(textwrap.wrap(capi(m.doc), 80)) + "\n")
self.fwrite(f, '"""\n')
self.fwrite(f, "module " + m.name + "\n\n")
if level == 1:
self.fwrite(
f, 'const {0}_API_VERSION = "{1}.{2}.{3}"\n'.format(
ns.upper(), self.version_major, self.version_minor,
self.version_patch))
self.fwrite(
f, 'const {0}_API_VERSION_MAJOR = {1}\n'.format(
ns.upper(), self.version_major))
self.fwrite(
f, 'const {0}_API_VERSION_MINOR = {1}\n'.format(
ns.upper(), self.version_minor))
self.fwrite(
f, 'const {0}_API_VERSION_PATCH = {1}\n'.format(
ns.upper(), self.version_patch))
self.fwrite(f, 'const libdir = dirname(@__FILE__)\n')
self.fwrite(
f, 'const libname = Sys.iswindows() ? "' + ns +
'-{0}.{1}'.format(self.version_major, self.version_minor) +
'.dll" : "lib' + ns + '"\n')
self.fwrite(f, 'import Libdl\n')
self.fwrite(
f, 'const lib = Libdl.find_library([libname], [libdir])\n')
else:
self.fwrite(f, "import " + ("." * level) + ns + "\n")
if c_mpath:
c_mpath += m.name[0].upper() + m.name[1:]
jl_mpath += m.name + "."
else:
c_mpath = m.name
jl_mpath = m.name + "."
for fun in m.fs:
write_function(f, fun, c_mpath, jl_mpath)
for module in m.submodules:
write_module(f, module, c_mpath, jl_mpath, level + 1)
self.fwrite(f, "\nend # end of module " + m.name + "\n")
self.current_lineno = 1
with open(ns + ".jl", "w") as f:
self.fwrite(
f,
julia_header.format(self.copyright, self.issues, self.code,
self.version_major, self.version_minor,
self.version_patch))
for module in self.modules:
write_module(f, module, "", "", 1)
def write_fortran(self):
def write_module(module, c_namespace, cpp_namespace, indent):
cpp_namespace += module.name + "::"
if c_namespace:
c_namespace += module.name[0].upper() + module.name[1:]
else:
c_namespace = module.name
indent += " "
for rtype, name, args, doc, special in module.fs:
# *f.h
fname = c_namespace + name[0].upper() + name[1:]
# output doc
self.fwrite(
f,
"\n! " + "\n! ".join(textwrap.wrap(doc, 75)) + "\n")
fnameapi = "! " + ns.upper() + "_API " + (rtype.rc_type if rtype else
"void") + " " + fname + "("
self.flog('f', cpp_namespace.replace('::', '/') + name)
if (len(fname) < 45) :
# output fortran header
fnamef = ' '*8 + ("function" if rtype else "subroutine") + ' ' + fname + "("
self.fwrite(
f, fnamef + "\n & " + (",\n & ").join(
list((a.fortran_name_pre + a.name + a.fortran_name_post for a in args + (oint("ierr"), )))) + ")\n")
left = " "
self.fwrite(
f,
" & bind(C, name = \"" + fname + "\")" + "\n")
self.fwrite(
f,
left + "use, intrinsic :: iso_c_binding" + "\n")
if rtype :
self.fwrite(
f,
left + (rtype.fortran_type) + "::" + fname + "\n")
self.fwrite(
f, ("").join(
list(( left + " " + a.fortran_type + "::"
+ a.name + a.fortran_type_post
+ "\n" for a in args + (oint("ierr"), ) ))
)
)
self.fwrite(
f,
left + "end " + ("function" if rtype else "subroutine")
+ " " + fname + "\n")
for m in module.submodules:
write_module(m, c_namespace, cpp_namespace, indent)
self.current_lineno = 1
with open(ns + "f.h", "w") as f:
self.fwrite(
f,
fortran_header.format(self.copyright, self.issues,
ns.upper(), self.code,
self.version_major, self.version_minor,
self.version_patch, ns))
for module in self.modules:
write_module(module, "", "", "")
self.fwrite(f, fortran_footer)
def write_texi(self):
def tryint(s):
try:
return int(s)
except:
return s
def alphanum_key(s):
return [tryint(c) for c in re.split('([0-9]+)', s)]
def get_file_data(path, ext):
data = []
for r, d, f in os.walk(path):
for file in f:
if file.endswith(ext):
filename = os.path.join(r, file)
contents = []
for line in open(filename, 'r'):
contents.append(line)
data.append([filename, contents])
data.sort(key=lambda x: alphanum_key(x[0]))
return data
def find_function(lang, name, data):
only_unique = False # only report unique matches?
in_comments = False # report matches in comments?
if lang == 'Python':
func = name.replace('/', '.')
comment = '#'
else:
func = name.replace('/', '::')
comment = '//'
match = []
unique = set()
for file in data:
l = 0
for line in file[1]:
l = l + 1
# allow white space between func name and (
if re.search(func + '\s*\(', line):
strip = re.sub(r'\s+', '', line)
# don't report matches in comments
if not in_comments and strip.startswith(comment):
continue
# only report a given match once
if (not only_unique) or (strip not in unique):
match.append((file[0], l))
unique.add(strip)
break # report only one match per file
else:
unique.add(strip)
return match
def write_module(module, path, node, node_next, node_prev, cpp_data,
py_data):
f.write("@node " + node + ", " + node_next + ", " + node_prev +
", Gmsh API\n")
f.write("@section Namespace @code{" + path + "}: " + module.doc +
"\n\n")
f.write("@ftable @code\n")
for rtype, name, args, doc, special in module.fs:
tfull = path + '/' + name
if len(tfull) > 40: # insert discretionary hyphen if too long
for i in range(40, len(tfull)):
if tfull[i].isupper():
tfull = tfull[:i] + '@-' + tfull[i:]
break
f.write("@item " + tfull + "\n")
tdoc = doc.replace("`", "@code{").replace("'", "}")
f.write("\n".join(textwrap.wrap(tdoc, 80)) + "\n\n")
f.write("@table @asis\n")
iargs = list(a for a in args if not a.out)
oargs = list(a for a in args if a.out)
f.write("@item " + "Input:\n" + (", ".join(
("@code{" + iarg.texi + "}")
for iarg in iargs) if len(iargs) else "-") + "\n")
f.write("@item " + "Output:\n" + (", ".join(
("@code{" + oarg.name + "}")
for oarg in oargs) if len(oargs) else "-") + "\n")
f.write("@item " + "Return:\n" +
(rtype.rtexi_type if rtype else "-") + "\n")
f.write("@item " + "Language-specific definition:\n")
f.write("@url{@value{GITLAB-PREFIX}/api/gmsh.h#L" +
str(self.api_lineno['cpp'][path + '/' + name]) +
",C++}")
f.write(", @url{@value{GITLAB-PREFIX}/api/gmshc.h#L" +
str(self.api_lineno['c'][path + '/' + name]) + ",C}")
try:
f.write(", @url{@value{GITLAB-PREFIX}/api/gmsh.py#L" +
str(self.api_lineno['py'][path + '/' + name]) +
",Python}")
except:
pass
try:
f.write(", @url{@value{GITLAB-PREFIX}/api/gmsh.jl#L" +
str(self.api_lineno['jl'][path + '/' + name]) +
",Julia}")
except:
pass
f.write("\n")
cpp = find_function('C++', path + '/' + name, cpp_data)
py = find_function('Python', path + '/' + name, py_data)
def write_matches(lang, matches, max_matches):
f.write(lang + ' (')
for i in range(min(max_matches,
len(matches))): # write max 5 matches
if i > 0: f.write(', ')
f.write('@url{@value{GITLAB-PREFIX}/' +
matches[i][0][3:] + '#L' + str(matches[i][1]) +
',' + os.path.basename(matches[i][0]) + '}')
if len(matches) > max_matches: f.write(', ...')
f.write(')')
if len(cpp) or len(py):
f.write("@item " + "Examples:\n")
if len(cpp):
write_matches("C++", cpp, 5)
if len(py): f.write(', ')
if len(py):
write_matches("Python", py, 5)
f.write("\n")
f.write("@end table\n\n")
f.write("@end ftable\n\n")
with open("../doc/texinfo/api.texi", "w") as f:
f.write(
"@c This file was generated by api/gen.py: do not edit manually!\n\n"
)
def flatten_module(flat, module, path):
p = path + ("/" if len(path) else "") + module.name
flat.append((module, p))
for m in module.submodules:
flatten_module(flat, m, p)
def node_name(n):
return "Namespace " + n[1]
flat = []
for m in self.modules:
flatten_module(flat, m, "")
N = len(flat)
f.write("@menu\n")
for i in range(N):
f.write("* " + node_name(flat[i]) + "::\n")
f.write("@end menu\n\n")
cpp_data = get_file_data('../tutorials', '.cpp')
cpp_data.extend(get_file_data('../exampls/api', '.cpp'))
py_data = get_file_data('../tutorials', '.py')
py_data.extend(get_file_data('../examples/api', '.py'))
for i in range(N):
write_module(flat[i][0], flat[i][1], node_name(flat[i]),
"" if i == N - 1 else node_name(flat[i + 1]),
"" if i == 0 else node_name(flat[i - 1]),
cpp_data, py_data)