- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi @Steve,
Thank you so much for your `module str_routines`. It can convert C char array to a Fortran string and works great in Windows x64 (Microsoft Visual Studio 2019 + Intel Visual Fortran 2019).
Now, I'm trying to use it on Linux (Ubuntu 18 x64) but I got a segmentation fault error inside of it and I don't know why it's happening.
Here is my C++ source-code:
extern "C" { void f_subroutine(const char* c_str); } int main(void) { const char c_str[5] = "test"; f_subroutine(c_str); return 0; }
Here is my Fortran source-code:
module str_routines contains subroutine C_F_STRPOINTER (STRARRAY, FSTRPTR, MAXLEN) use, intrinsic :: ISO_C_BINDING implicit none character, dimension(*), target, intent(in) :: STRARRAY character(:), pointer, intent(out) :: FSTRPTR integer, intent(in), optional :: MAXLEN integer :: curlen curlen = 0 do curlen = curlen +1 if (PRESENT(MAXLEN)) THEN if (curlen > MAXLEN) exit end if if (STRARRAY(CURLEN) == CHAR(0)) exit end do call doassign(C_LOC(STRARRAY), FSTRPTR, curlen-1) contains subroutine doassign(CSTRPTR, FSTRPTR, STRLEN) type(C_PTR), intent(in) :: CSTRPTR character(:), pointer, intent(out) :: FSTRPTR integer, intent(in) :: STRLEN character(STRLEN), pointer :: p call C_F_POINTER(CSTRPTR, p) FSTRPTR => p return end subroutine doassign end subroutine C_F_STRPOINTER end module str_routines subroutine f_subroutine(c_str) bind(C) use, intrinsic :: ISO_C_BINDING use str_routines implicit none character(kind=C_CHAR), target, intent(in) :: c_str(*) character(kind=C_CHAR, len=:), pointer :: f_str ! Convert C char array to Fortran string: call C_F_STRPOINTER (c_str, f_str) end subroutine f_subroutine
Compile and link sequence:
// Compile the Fortran file to a object: gfortran -c -g fortran.90 // Create a Linux static library ar -cr libmylib.a fortran.o // Compile C++ and link it with the Fortran static library g++ -Wall main.cpp -L. -lmylib -lgfortran -o app // Run it: ./app // Console error: Segmentation fault (core dumped)
To inspect what it causing this run-time error, I debugged it using Qt Creator IDE on Linux.
Here is my debug session and local variables values:
As you can see, I got a "Segmentation Fault" error in the line 34.
FSTRPTR => p
Could you please help me to solve it?
Thank you again,
Nycholas Maia
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Did you rebuild the Fortran library after changing the setting? If yes and you still have the problem, add ifmodintr.lib to "Additional Dependencies" in the C++ project's Linker properties.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You're using gfortran - I can't help with that. It may be that gfortran doesn't fully or properly implement deferred-length character pointers. I notice in your screenshot that the debugger claims that the type of _fstrptr is integer(4) - that doesn't seem right.
Come back here if it doesn't work in Intel Fortran.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This is for other readers who may be open to advice such as the one provided by Jim Dempsey where he states, "As it stands, a helper function is required on one side or the other. My preference is to do this on the C/C++ side.", in this other thread by OP: https://software.intel.com/en-us/forums/intel-fortran-compiler/topic/815905 which then can lead to really short and simple code that is easier on both readers as well as processors:
#include <cstring> extern "C" { void f_subroutine(const char* , size_t); } int main(void) { char c_str[] = "Test"; //<-- Note no hard-wired length f_subroutine(c_str, strlen(c_str)); return 0; }
subroutine f_subroutine(c_str, lens) bind(C, name="f_subroutine") ! Module procedures are recommended use, intrinsic :: iso_c_binding, only : c_loc, c_f_pointer, c_char, c_size_t ! Argument list character(kind=c_char, len=1), target, intent(in) :: c_str(*) integer(kind=c_size_t), intent(in), value :: lens if ( lens > 0 ) then block character(kind=c_char, len=lens), pointer :: pfstr call c_f_pointer( c_loc(c_str), fptr=pfstr ) print *, "In f_subroutine: Fortran incarnation of c_str: ", pfstr pfstr => null() end block end if return end subroutine f_subroutine
Upon execution of code built with either gfortran or Intel Fortran, the output is as follows:
In f_subroutine: Fortran incarnation of c_str: Test
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Steve and FortranFan,
Thank you all for the informations.
I tried the FortranFan solution and it works perfect using gfortran. Just "copy and paste" and it works great!
Now, when I did the same thing using Intel Visual Fortran 2019 I got a compile-time error related with this Fortran source-code line:
call c_f_pointer( c_loc(c_str), fptr=pfstr )
So, Visual Studio 2019 give me theses erros below:
unresolved external symbol ISO_C_BINDING_mp_C_LOC_PRIVATE referenced in function f_subroutine unresolved external symbol c_f_pointer_set_scalar referenced in function f_subroutine
Question 1:
Do you have any ideas why it's happening when I use IVF 2019? How can I solve it?
Question 2:
FortranFan, in the C++ side, your source-code exemple have this C string observation:
char c_str[] = "Test"; //<-- Note no hard-wired length
It works good!
But this modified version below works good too (at moment, only tested using gfortran).
char c_str[30] = "Test";
It prints the correct C string with no blank spaces like the original one.
So, why should I use the original "hard-wired length"? Is there any C-Fortran interoperability advantages?
Thank you all,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You did not get a compile-time error. This is a link-time error and indicates you did not supply the proper libraries when you linked your code. You need to add ifmodintr.lib if you've disabled default library search rules.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>unresolved external symbol
Either bug or linking in incorrect Fortran runtime library.
BTW - c_loc should be an intrinsic function resolved at compile time, not an external function executed at runtime. This would seem to indicate bug.
Try adding just below BLOCK:
use, intrinsic :: iso_c_binding, only : c_loc, c_f_pointer, c_char
>>So, why should I use the original "hard-wired length"? Is there any C-Fortran interoperability advantages?
In the event you want to receive text. In this case though you would likely pass sizeof(c_str) as opposed to strlen(c_str), and modify helper function to, for input, use lesser value of the search for NULL or passed in length.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@Steve, you are right!
Now, I change the Fortran project configuration to:
disabled default library search rules: NO
And that "unresolved external" old error is gone.
So, in Visual Studio 2019, I have 1 solution with 2 projects:
- C++ console app
- Fortran Static Library
With this help from Steve, now I can compile the Fortran library project with no errros. Good!
So, the last linker error is when I try to build and link the C++ project with the Fortran library file. I got this linker error:
cannot open file 'ifconsol.lib'
I already added in the C++ project properties:
Linker -> General -> Additional Library Directories:
- C:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2019.4.245\windows\compiler\lib\intel64_win
- C:\Users\lamar\Desktop\f_str_lib\x64\Debug
Linker -> General -> Link Library Dependencies: YES
Linker -> Input -> Additional Dependecies: f_str_lib.lib; %(AdditionalDependencies)
2- Right-click on Solution name -> Project Dependencies: and set the correct dependency order.
AND In my Fortran Static Library project I setted:
Tools -> Options -> Intel Compilers and Tools -> Visual Fortran -> Compilers -> x64:
Includes:
C:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2019.4.245\windows\compiler\include
Libraries:
C:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2019.4.245\windows\compiler\lib\intel64_win
Finally, I followed this Intel tutorial:
https://software.intel.com/en-us/articles/configuring-visual-studio-for-mixed-language-applications
What more I have to do to link the 'ifconsol.lib' to my C++ application?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
UPDATE 1:
I followed the Intel Tutorial about mixed-language applications and set the configurations for use Intel Visual Fortran 2019 for build x64 applications.
After this, I cleaned my Solution and rebuild.
The Fortran Static library project compiles Ok! No errors!
But the C++ linker shows me these 2 old erros:
unresolved external symbol ISO_C_BINDING_mp_C_LOC_PRIVATE referenced in function f_subroutine c_str_test unresolved external symbol c_f_pointer_set_scalar referenced in function f_subroutine c_str_test
Before this configuration I had only the linker error about 'ifconsol.lib'...and if I go back to the old configurations (without Intel Tutorial) these 2 erros above still the same.
What I'm doing wrong?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Same problem as above. If you're building a mixed language application where the main program is not Fortran, set the "Disable default library search rules" to No in the Fortran Library project. It defaults to Yes as this is generally what you want when the main is Fortran.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I already did it...but it doesn't resolved the C++ linker problem.
Do you have any idea?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Did you rebuild the Fortran library after changing the setting? If yes and you still have the problem, add ifmodintr.lib to "Additional Dependencies" in the C++ project's Linker properties.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you @Steve! You are great!
Yes, I just add the 'ifmodintr.lib' to "Additional Dependencies" in the C++ project's Linker properties and all goes Ok!
Is there any documentation about this 'libraries dependencies'? In a future, how could I known which library name is missing in the "Additional Dependencies" field?
Thank you again!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Normally, when you compile a Fortran source, it adds linker directives to the object file naming the libraries it wants the linker to pull in. When you USE ISO_C_BINDING it adds a directive for ifmodintr.lib (you can see the OBJCOMMENT directive in the source for the module in the ifort include folder).
There is a compiler option to disable adding these directives (/libdir:[no]auto), which is what the "Disable OBJCOMMENT Library Names" property adjusts. For static library projects the default is Yes (don't include OBJCOMMENT directives), as one typically wants the main program to control this.
With a non-Fortran main, however, there's nothing to specify which Fortran support libraries are pulled in other than the OBJCOMMENT directives, so you generally want to include those in your library build.
I still think that if you had rebuilt your library with the option properly set that it would have worked ok for you. I had thought there was documentation on the list of libraries, but I can't find it. I did find a page "Specifying Consistent Library Types", but it is not only incomplete but woefully out of date (mentions libc.lib, which no longer exists, plus says "ifcore.lib" which never existed.) I will report this to Intel.
If you want to see the list of libraries the compiler wants, do a:
dumpbin -directives
on a compiled .obj. You'll get something like this:
Linker Directives ----------------- -defaultlib:ifconsol -defaultlib:libifcoremt -defaultlib:libifport -defaultlib:libmmt -defaultlib:LIBCMT -defaultlib:libirc -defaultlib:svml_dispmt -defaultlib:OLDNAMES
I would ignore OLDNAMES - that's a historical artifact. Note that the list of libraries will vary depending on other compiler options and modules used.
Last, now that this forum has been merged for all platforms, I need to say that all of the above applies to Windows only. Linux/Mac doesn't have a similar mechanism, leaving you to explicitly name all of the support libraries needed if you're not using "ifort" to link.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Maia, Nycholas wrote:..
Question 2:
FortranFan, in the C++ side, your source-code exemple have this C string observation:char c_str[] = "Test"; //<-- Note no hard-wired lengthIt works good!
But this modified version below works good too (at moment, only tested using gfortran).
char c_str[30] = "Test";It prints the correct C string with no blank spaces like the original one.
So, why should I use the original "hard-wired length"? Is there any C-Fortran interoperability advantages?
..
Re: "why should I use the original "hard-wired length"?," yes, why should you!? That was my point, that it's high-time coders moved beyond hard-wired string lengths that lead to so many issues: compile-time errors, run-time errors, wasted space. As a matter of good coding practice, whether it be in Fortran or other languages, coders can try to utilize the capabilities to right-size their data. And where Fortran falls short (like a true intrinsic derived type for strings, they should expect and request language improvements:
#include <iostream> using namespace std; extern "C" { void f_subroutine(const char* , size_t); } int main(void) { // No guessing as to the length of string constant string s = "../files/json_files/my_json_file.json"; cout << "length of string: " << s.size() << endl; f_subroutine( s.c_str(), s.size() ); return 0; }
Upon execution,
length of string: 37 In f_subroutine: Fortran incarnation of c_str: ../files/json_files/my_json_file.json
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you @FortranFan for your good explanation about this issue.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
FWIW>>
// No guessing as to the length of string constant string s = "../files/json_files/my_json_file.json";
s is not a string constant, it is declared as variable. Also note that the attribute of the segment(linker section) holding the buffer for s should contain Read/Write.
There is nothing to say that f_subroutine could not modify s. s could be declared with const and may place the buffer in a Read-Only segment when you really desire to have it a string constant.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jimdempseyatthecove (Blackbelt) wrote:FWIW>>
// No guessing as to the length of string constant string s = "../files/json_files/my_json_file.json";s is not a string constant, it is declared as variable. Also note that the attribute of the segment(linker section) holding the buffer for s should contain Read/Write.
There is nothing to say that f_subroutine could not modify s. s could be declared with const and may place the buffer in a Read-Only segment when you really desire to have it a string constant.
Jim Dempsey
Just to be clear: s is a variable, an object instance of 'string' class in C++. It's the string literal on the right-hand side of the assignment is what I meant by constant; per Fortran standard terminology, that would be a "character literal constant"

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page