Simulation Core
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

fortran_c_interop.F90 4.0 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. ! BSD 2-Clause License
  2. !
  3. ! Copyright (c) 2021-2022, Hewlett Packard Enterprise
  4. ! All rights reserved.
  5. !
  6. ! Redistribution and use in source and binary forms, with or without
  7. ! modification, are permitted provided that the following conditions are met:
  8. !
  9. ! 1. Redistributions of source code must retain the above copyright notice, this
  10. ! list of conditions and the following disclaimer.
  11. !
  12. ! 2. Redistributions in binary form must reproduce the above copyright notice,
  13. ! this list of conditions and the following disclaimer in the documentation
  14. ! and/or other materials provided with the distribution.
  15. !
  16. ! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17. ! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. ! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. ! DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  20. ! FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. ! DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  22. ! SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  23. ! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  24. ! OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  25. ! OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. module fortran_c_interop
  27. use iso_c_binding, only : c_ptr, c_char, c_size_t, c_loc, c_null_ptr, c_int
  28. implicit none; private
  29. integer, parameter, public :: enum_kind = c_int !< The kind of integer equivalent to a C enum. According
  30. !! to the standard this is a c_int
  31. public :: convert_char_array_to_c
  32. contains
  33. !> Returns pointers to the start of each string and lengths for each string in a Fortran character array
  34. subroutine convert_char_array_to_c(character_array_f, character_array_c, string_ptrs, ptr_to_string_ptrs, &
  35. string_lengths, ptr_to_string_lengths, n_strings )
  36. !> The 2D Fortran character array
  37. character(len=*), dimension(:), intent(in ) :: character_array_f
  38. !> The character array converted to c_character types
  39. character(kind=c_char,len=:), dimension(:), allocatable, target, intent( out) :: character_array_c
  40. !> C-style pointers to the start of each string
  41. type(c_ptr), dimension(:), allocatable, target, intent( out) :: string_ptrs
  42. !> A pointer to the the string pointers
  43. type(c_ptr), intent( out) :: ptr_to_string_ptrs
  44. !> The length of each string
  45. integer(kind=c_size_t), dimension(:), allocatable, target, intent( out) :: string_lengths
  46. !> Pointer to the array containing the string_lengths
  47. type(c_ptr), intent( out) :: ptr_to_string_lengths
  48. !> The length of each string
  49. integer(kind=c_size_t), intent( out) :: n_strings
  50. integer :: i, max_length, length
  51. ! Find the size of the 2D array and allocate some of the 1D arrays
  52. n_strings= size(character_array_f)
  53. allocate(string_lengths(n_strings))
  54. allocate(string_ptrs(n_strings))
  55. ! Need to find the length of the string, so we can allocate the c_array
  56. max_length = 0
  57. do i=1,n_strings
  58. length = len_trim(character_array_f(i))
  59. max_length = max(max_length, length)
  60. string_lengths(i) = length
  61. enddo
  62. ptr_to_string_lengths = c_loc(string_lengths)
  63. allocate(character(len=max_length) :: character_array_c(n_strings))
  64. ! Copy the character into a c_char and create pointers to each of the strings
  65. do i=1,n_strings
  66. if (string_lengths(i) .gt. 0) then
  67. character_array_c(i) = transfer(character_array_f(i),character_array_c(i))
  68. string_ptrs(i) = c_loc(character_array_c(i))
  69. else
  70. string_ptrs(i) = c_null_ptr;
  71. endif
  72. enddo
  73. ptr_to_string_ptrs = c_loc(string_ptrs)
  74. end subroutine convert_char_array_to_c
  75. end module fortran_c_interop