Skip to content

Commit d298d2c

Browse files
committed
add C=>Fortran struct
1 parent 3477ffc commit d298d2c

File tree

7 files changed

+133
-0
lines changed

7 files changed

+133
-0
lines changed

src/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ add_test(NAME C_Fortran_error
2525
COMMAND ${CMAKE_COMMAND} -Dexe=$<TARGET_FILE:c_fortran_error> -Dexp_code=42 -P ${PROJECT_SOURCE_DIR}/cmake/test_error.cmake
2626
)
2727

28+
add_executable(c_fortran_struct c/struct_main.c)
29+
target_link_libraries(c_fortran_struct PRIVATE struct_fortran)
30+
add_test(NAME C_Fortran_struct COMMAND $<TARGET_FILE:c_fortran_struct>)
31+
2832
# -- C++ calling Fortran
2933
add_executable(cxx_call_fortran cxx/main.cxx)
3034
target_link_libraries(cxx_call_fortran PRIVATE math_fortran)
@@ -38,6 +42,10 @@ add_test(NAME C++_Fortran_error
3842
COMMAND ${CMAKE_COMMAND} -Dexe=$<TARGET_FILE:cxx_fortran_error> -Dexp_code=42 -P ${PROJECT_SOURCE_DIR}/cmake/test_error.cmake
3943
)
4044

45+
add_executable(cxx_fortran_struct cxx/struct_main.cxx)
46+
target_link_libraries(cxx_fortran_struct PRIVATE struct_fortran)
47+
add_test(NAME C++_Fortran_struct COMMAND $<TARGET_FILE:cxx_fortran_struct>)
48+
4149
# -- test wrapup
4250
set_tests_properties(C++_Fortran_math C++_Fortran_error Fortran_call_C Fortran_call_C++ PROPERTIES
4351
TIMEOUT 5

src/c/struct_main.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include <stdbool.h>
2+
#include <string.h>
3+
4+
struct params {
5+
// order and lengths must match in Fortran and C
6+
int my_int;
7+
bool my_bool;
8+
int Lmy_char;
9+
char my_char[1000];
10+
};
11+
12+
extern void struct_check(struct params *);
13+
14+
int main(void) {
15+
16+
struct params s;
17+
18+
s.my_int = 123;
19+
s.my_bool = true;
20+
strcpy(s.my_char, "Hello");
21+
s.Lmy_char = strlen(s.my_char);
22+
23+
struct_check(&s);
24+
25+
return 0;
26+
27+
}

src/cxx/struct_main.cxx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include <cstring>
2+
3+
struct params {
4+
// order and lengths must match in Fortran and C
5+
int my_int;
6+
bool my_bool;
7+
int Lmy_char;
8+
char my_char[1000];
9+
};
10+
11+
extern "C" void struct_check(struct params *);
12+
13+
int main(void) {
14+
15+
struct params s;
16+
17+
s.my_int = 123;
18+
s.my_bool = true;
19+
strcpy(s.my_char, "Hello");
20+
s.Lmy_char = strlen(s.my_char);
21+
22+
struct_check(&s);
23+
24+
return 0;
25+
26+
}

src/fortran/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
add_library(math_fortran OBJECT math.f90)
22

33
add_library(error_fortran OBJECT error.f90)
4+
5+
add_library(struct_fortran OBJECT struct.f90)

src/fortran/meson.build

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
math_fortran = library('math_fortran', 'math.f90')
22

33
error_fortran = library('error_fortran', 'error.f90')
4+
5+
struct_fortran = library('struct_fortran', 'struct.f90')

src/fortran/struct.f90

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
module struct_rx
2+
3+
use, intrinsic :: iso_c_binding, only : c_int, c_bool, c_char, c_null_char
4+
5+
implicit none (type, external)
6+
7+
8+
type, bind(C) :: my_struct
9+
!! order and length must match in Fortran and C
10+
integer(c_int) :: my_int
11+
logical(c_bool) :: my_bool
12+
integer(c_int) :: Lmy_char
13+
character(kind=c_char) :: my_char(1000)
14+
!! character(kind=c_char) in bind(c) type cannot be allocatable. Just have to make it "long enough"
15+
!! or use iso_c_binding.h stuff
16+
17+
end type my_struct
18+
19+
20+
contains
21+
22+
23+
pure subroutine struct_check(s) bind(C)
24+
25+
type(my_struct), intent(in) :: s
26+
27+
character(:), allocatable :: my_char
28+
29+
if(s%my_int /= 123) error stop "my_int /= 123"
30+
if(.not. s%my_bool) error stop "my_bool /= .true."
31+
if(s%Lmy_char /= 5) error stop "Lmy_char /= 5"
32+
33+
block
34+
character(s%Lmy_char) :: buf
35+
integer :: i
36+
buf = "" !< ensure buf has no garbage characters
37+
38+
do i = 1, s%Lmy_char
39+
if (s%my_char(i) == c_null_char) exit
40+
buf(i:i) = s%my_char(i)
41+
enddo
42+
my_char = buf
43+
end block
44+
45+
if(my_char /= "Hello") error stop "my_char /= 'Hello'"
46+
47+
end subroutine struct_check
48+
49+
50+
end module struct_rx

src/meson.build

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ test('C Fortran error', c_fortran_error,
3030
timeout: 5,
3131
should_fail: true)
3232

33+
c_fortran_struct = executable('c_fortran_struct',
34+
sources: files('c/struct_main.c'),
35+
link_with: struct_fortran,
36+
link_language: 'fortran'
37+
)
38+
test('C Fortran struct', c_fortran_struct,
39+
timeout: 5
40+
)
41+
3342
# -- C++ calling Fortran
3443
cxx_call_fortran = executable('cxx_call_fortran',
3544
sources: files('cxx/main.cxx'),
@@ -45,3 +54,12 @@ cxx_fortran_error = executable('cxx_fortran_error',
4554
test('C++ Fortran error', cxx_fortran_error,
4655
timeout: 5,
4756
should_fail: true)
57+
58+
cxx_fortran_struct = executable('cxx_fortran_struct',
59+
sources: files('cxx/struct_main.cxx'),
60+
link_with: struct_fortran,
61+
link_language: 'fortran'
62+
)
63+
test('C++ Fortran struct', cxx_fortran_struct,
64+
timeout: 5
65+
)

0 commit comments

Comments
 (0)