Developer guide¶
Debugging¶
h2lib.H2Lib is wrapper function that returns a H2LibThread instance that either runs in current thread H2Lib(subprocess=False) or in a separate process (default).
Debugging e.g. in visual studio is possible when if subprocess=False
Add method¶
Add function or subroutine in fortran¶
Add function to one of the existing fortran files or to a new one e.g. in the lib folder. New files must be added to the src variable in the lib/cmakelist.txt file (lib/*.f90 files are all included).
Note, these example functions are already defined in lib/test_module.f90
function myfunction(int, dbl) bind(C, name='myfunction')
!DEC$ ATTRIBUTES DLLEXPORT :: myfunction
integer*8, intent(in) :: int
real(c_double), intent(in) :: dbl
real(c_double) :: myfunction
myfunction = int + dbl
end function
subroutine mysubroutine(str_arr, dbl_array) bind(C, name='mysubroutine')
!DEC$ ATTRIBUTES DLLEXPORT :: mysubroutine
character(kind=c_char, len=1), intent(in) :: str_arr(1024)
character(len=256) :: str
real(c_double), intent(inout), dimension(2) :: dbl_array
call cstring2fortran(str_arr, str)
print *, str
dbl_array = dbl_array + 1
end subroutine
Build the library and copy the dll/so to src-python/h2lib/HAWC2Lib.dll (automatically done in the h2lib setup process).
Moreover the function/subroutine names must be appended to the lib/export.txt file.
Add python interface to function/subroutine¶
After adding the method name to lib/export.txt you can run python make_lib_signatures.py from the lib folder
This will update src-python/h2lib/h2lib_signatures.py with the following methods, which makes autocomplete work in some editors:
def myfunction(self, int, dbl, restype):
'''function myfunction(int, dbl) bind(C, name='myfunction')
!DEC$ ATTRIBUTES DLLEXPORT :: myfunction
integer*8, intent(in) :: int
real(c_double), intent(in) :: dbl
real(c_double) :: myfunction
end function'''
return self.get_lib_function('myfunction')(int, dbl, restype=restype)
def mysubroutine(self, str_arr, dbl_arr):
'''subroutine mysubroutine(str_arr, dbl_arr) bind(C, name='mysubroutine')
character(kind=c_char, len=1), intent(inout) :: str_arr(20)
real(c_double), intent(inout), dimension(2) :: dbl_arr
end subroutine'''
return self.get_lib_function('mysubroutine')(str_arr, dbl_arr)
You can now call the methods directly after converting the inputs to ctypes. The library functions, however, is wrapped with features that changes current working directory, suppresses output (if specified during instantiation, i.e. H2Lib(suppress_output=True)) and tries to convert python types into ctypes. The type conversion works for most standard python and numpy types (if properly specified).
[1]:
from h2lib import H2Lib
import numpy as np
with H2Lib(subprocess=False, suppress_output=False) as h2:
print(h2.myfunction(1, 2., restype=np.float64)) # return (updated) input arguements and return value
s = "hello" + " " * 20
print(h2.mysubroutine(s, np.array([3.,4]))) # return (updated) input arguements and subroutine return value
([1, 2.0], 3.0)
(['world ', array([4., 5.])], 152)
In the code above the call to h2.myfunction only works because the 1 is an interger and 2. is a float as the wrapper as default converts integers to 64-bit integer and floats to 64 bit floats. Similarly, the array becomes a np.float64 because 3. is a float.
To please the user you can override the method, typically by adding methods to the h2lib.H2Lib class. In this example we extend H2LibThread:
[2]:
from h2lib._h2lib import H2LibThread
class MyLib(H2LibThread):
def myfunction(self, i, d):
return H2LibThread.myfunction(self, int=int(i), dbl=float(d), # convert to int and float
restype=np.float64 # set return type
)[1] # return output only
def mysubroutine(self, s, dbl_arr):
s, dbl_arr = H2LibThread.mysubroutine(self, s.ljust(20), # space pad string to have length 32
np.asarray(dbl_arr).astype(np.float64) # convert to np.float64 array
)[0] # return arguments only
return s.strip(), dbl_arr
with MyLib(suppress_output=False) as h2:
print (h2.myfunction(1,2))
print (h2.mysubroutine("hello", [3,4]))
3.0
('world', array([4., 5.]))
[ ]: