Skip to content

Commit 59a564b

Browse files
committed
iso_fortran_binding string
1 parent be1a0c0 commit 59a564b

7 files changed

Lines changed: 80 additions & 3 deletions

File tree

test/iso_fortran_binding/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ if(HAVE_C_CHAR_PTR)
3232
add_test(NAME CFI_establish_string COMMAND cfi_establish_string)
3333

3434
if(HAVE_CFI_CDESC)
35+
add_executable(string_inout_c string_inout.c string_inout.f90)
36+
set_property(TARGET string_inout_c PROPERTY LINKER_LANGUAGE Fortran)
37+
add_test(NAME StringInOutC COMMAND string_inout_c)
38+
39+
add_executable(string_inout_cpp string_inout.cpp string_inout.f90)
40+
set_property(TARGET string_inout_cpp PROPERTY LINKER_LANGUAGE Fortran)
41+
add_test(NAME StringInOutCPP COMMAND string_inout_cpp)
42+
3543
add_executable(string_array string_array.cpp string_array.f90)
3644
set_property(TARGET string_array PROPERTY LINKER_LANGUAGE CXX)
3745
target_compile_options(string_array PRIVATE "$<$<COMPILE_LANG_AND_ID:Fortran,GNU>:-Wno-uninitialized>")

test/iso_fortran_binding/c_string.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// https://fortran-lang.discourse.group/t/experiment-dealing-with-a-pointer-to-a-string-from-c/930/3
22
#include <string.h>
3-
#include "ISO_Fortran_binding.h"
3+
#include <ISO_Fortran_binding.h>
44

55
static char *str = "Hello";
66

test/iso_fortran_binding/string_array.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include <iostream>
66
#include <cstdlib>
77

8-
#include "ISO_Fortran_binding.h"
8+
#include <ISO_Fortran_binding.h>
99

1010
extern "C" {
1111
// Prototype for the Fortran procedures
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <string.h>
2+
3+
#include <ISO_Fortran_binding.h>
4+
5+
void process_strings_cfi(const CFI_cdesc_t *in_desc, CFI_cdesc_t *out_desc) {
6+
// 1. Get exact lengths directly from the Fortran descriptor
7+
size_t in_len = in_desc->elem_len;
8+
size_t out_len = out_desc->elem_len;
9+
10+
// 2. Direct pointer access to Fortran's memory
11+
char *in_ptr = (char*)(in_desc->base_addr);
12+
char *out_ptr = (char*)(out_desc->base_addr);
13+
14+
// Note: Fortran strings are NOT null-terminated!
15+
// You must use bounded memory operations:
16+
// printf("C received exact characters: %.*s\n", (int)in_len, in_ptr);
17+
18+
// Write safely back to Fortran's allocated memory space
19+
memset(out_ptr, ' ', out_len); // Clear with Fortran space-padding
20+
strncpy(out_ptr, "Success", out_len < 7 ? out_len : 7);
21+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include <algorithm> // for std::min
2+
#include <string>
3+
4+
#include <ISO_Fortran_binding.h>
5+
6+
extern "C" {
7+
void process_strings_cfi(const CFI_cdesc_t *, CFI_cdesc_t *);
8+
}
9+
10+
11+
void process_strings_cfi(const CFI_cdesc_t *in_desc, CFI_cdesc_t *out_desc) {
12+
const std::string::size_type in_len = in_desc->elem_len;
13+
const std::string::size_type out_len = out_desc->elem_len;
14+
15+
const char *in_ptr = static_cast<const char *>(in_desc->base_addr);
16+
char *out_ptr = static_cast<char *>(out_desc->base_addr);
17+
18+
// Fortran character data is fixed-width and not null-terminated.
19+
const std::string in_value(in_ptr, in_len);
20+
(void)in_value;
21+
const std::string out_value("Success");
22+
23+
// Copy into Fortran buffer using space-padding semantics.
24+
std::string fortran_out(out_len, ' ');
25+
fortran_out.replace(0, std::min(out_len, out_value.size()), out_value, 0, std::min(out_len, out_value.size()));
26+
fortran_out.copy(out_ptr, out_len);
27+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
program string_inout_cpp
2+
3+
implicit none
4+
5+
interface
6+
subroutine process_strings_direct(in_str, out_str) bind(C, name="process_strings_cfi")
7+
character(len=*), intent(in) :: in_str
8+
character(len=*), intent(out) :: out_str
9+
end subroutine process_strings_direct
10+
end interface
11+
12+
13+
character(len=20) :: input_str = "Hello from Fortran!"
14+
character(len=20) :: output_str
15+
16+
call process_strings_direct(input_str, output_str)
17+
18+
print *, "Fortran sent: ", trim(input_str)
19+
print *, "Fortran received: ", trim(output_str)
20+
21+
end program

test/iso_fortran_binding/string_view.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#include <string_view>
44
#include <iostream>
55

6-
#include "ISO_Fortran_binding.h"
6+
#include <ISO_Fortran_binding.h>
77

88
extern "C" {
99
void echo_c( const CFI_cdesc_t* Fstr )

0 commit comments

Comments
 (0)