Rocksolid Light

Welcome to RetroBBS

mail  files  register  newsreader  groups  login

Message-ID:  

You are in a maze of little twisting passages, all different.


devel / comp.lang.c++ / Re: Problem with calling C++ from Fortran

Re: Problem with calling C++ from Fortran

<ac4c9220-8eb6-41d7-a5ad-522e33c55d28n@googlegroups.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=1469&group=comp.lang.c%2B%2B#1469

  copy link   Newsgroups: comp.lang.c++
X-Received: by 2002:a05:620a:2b87:b0:76f:58a:8ffc with SMTP id dz7-20020a05620a2b8700b0076f058a8ffcmr231222qkb.7.1694528107561;
Tue, 12 Sep 2023 07:15:07 -0700 (PDT)
X-Received: by 2002:a17:902:f0ca:b0:1b9:df8f:888c with SMTP id
v10-20020a170902f0ca00b001b9df8f888cmr4078694pla.8.1694528107328; Tue, 12 Sep
2023 07:15:07 -0700 (PDT)
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!usenet.blueworldhosting.com!diablo1.usenet.blueworldhosting.com!peer02.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.c++
Date: Tue, 12 Sep 2023 07:15:06 -0700 (PDT)
In-Reply-To: <udp8l4$1frsv$1@dont-email.me>
Injection-Info: google-groups.googlegroups.com; posting-host=199.203.251.52; posting-account=ow8VOgoAAAAfiGNvoH__Y4ADRwQF1hZW
NNTP-Posting-Host: 199.203.251.52
References: <udhbs9$e5d$1@dont-email.me> <udhcaj$j8l$1@dont-email.me>
<udkdu9$itm4$1@dont-email.me> <87o7iajh8b.fsf@bsb.me.uk> <udmvg7$11r4u$1@dont-email.me>
<87cyyoqoka.fsf@bsb.me.uk> <udp8l4$1frsv$1@dont-email.me>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <ac4c9220-8eb6-41d7-a5ad-522e33c55d28n@googlegroups.com>
Subject: Re: Problem with calling C++ from Fortran
From: already5chosen@yahoo.com (Michael S)
Injection-Date: Tue, 12 Sep 2023 14:15:07 +0000
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
X-Received-Bytes: 10198
 by: Michael S - Tue, 12 Sep 2023 14:15 UTC

On Tuesday, September 12, 2023 at 11:48:55 AM UTC+3, db wrote:
> On 12.09.2023 01.26, Ben Bacarisse wrote:
> > db <dieterh...@gmail.com> writes:
> >
> >> On 10.09.2023 15.22, Ben Bacarisse wrote:
> >>> db <dieterh...@gmail.com> writes:
> >>>
> >>>> On 09.09.2023 11.02, Mut...@dastardlyhq.com wrote:
> >>>>> On Sat, 9 Sep 2023 10:54:33 +0200
> >>>>> db <dieterh...@gmail.com> wrote:
> >>>>>> but now it says that C-double doesn't exist.
> >>>>>>
> >>>>>> Any ideas?
> >>>>> C++ mangles function names so that the name you give the function isn't
> >>>>> the
> >>>>> name the dynamic loader sees in the binary. You need to put this around whatever
> >>>>> function you want to call from Fortran so it has C style linkage which means
> >>>>> the name remains the same:
> >>>>> extern "C" {
> >>>>> void calledFromFortran()
> >>>>> {
> >>>>> :
> >>>>> }
> >>>>> }
> >>>>>
> >>>> Where should this go in the code? I added it at the end as is,
> >>>> and now I get this:
> >>>>
> >>>> ~/ownlib90/tests> ./jbandtest
> >>>> jband.cpp:88:1: error: expected initializer before 'extern'
> >>>> 88 | extern "C" {
> >>>> | ^~~~~~
> >>>> jband.cpp:96:1: error: expected unqualified-id before '{' token
> >>>> 96 | {
> >>>> | ^
> >>>> jband.cpp: In function 'void calledFromFortran()':
> >>>> jband.cpp:350:9: error: expected primary-expression before ':' token
> >>>> 350 | :
> >>>> ...
> >>> You are giving people very little to go on. There's an unknown command
> >>> (./jbandtest) the gives some errors where only one line of code can be
> >>> seen.
> >>> Can you produce a cut-down version to the program that shows the same
> >>> error -- mimimal example of the C++ and of the Fortran that should
> >>> calls it but which fails? That would mean you could post the code.
> >>> If that is not possible, can you link to the source so those who know
> >>> both C++ and Fortran can take a proper look?
> >>
> >> I put the C++ function here: www.dieterbritz.dk/jband.cpp
> >> After getting errors about the extern lines, whch I had
> >> added at the end, I shifted it to near the start:
> >>
> >> #include <iostream>
> >> #include <fstream>
> >> #include <iomanip>
> >> #include "math.h"
> >>
> >> using namespace std;
> >>
> >> extern "C" {
> >>
> >> void calledFromFortran()
> >> {
> >> :
> >> }
> >>
> >> }
> >
> > Remove them all. You have two options. One: correct the C++. To do
> > this put this, and only this,
> >
> > extern "C" {
> > const long double iband(const long double tbar);
> > }
> >
> > just after the #include lines. This is perfect (the first const is a
> > meaningless word here and the compiler may warn you about that) but it
> > will do.
> >
> > Next replace
> >
> > #include "math.h"
> >
> > with
> >
> > #include <math.h>
> >
> > I'd also remove the two unnecessary #include lines (for iomanip and
> > fstream). All of these are "tidying up". Only the extern "C" part I
> > gave corrects an actual mistake.
> >
> > The second option is the turn the code in C which links directly with
> > Fortran. The only C++ used by the code is one "cout << " line (not a
> > good way to report an error, but that's not important right now) and a
> > setting for pi that is not a compile-time constant (4*atanl(1)) written
> > in a more fussy way.
> >
> > To convert to C, copy the file to jband.c (rather than .cpp) and replce
> > the declaration for pi. Given the code is littered with explicit 21
> > digits decimals (a little more than the precision of C's usualy long
> > double type) I would just write
> >
> > static const long double pi = 3.14159265358979323846L;
> >
> > Now replace the cout line with
> >
> > fputs("\nError in stredges::iband(): tbar must be > 0", stderr);
> >
> > This writes the message to the error stream and put only these two
> > include lines at the top:
> >
> > #include <math.h>
> > #include <stdio.h>
> >
> > Now the file is C code.
> >
> > Frankly, this is the way I'd go, since linking C is just that bit
> > simpler than linking C++. But if the code is going to become fully
> > fledged (and complex) C++, obviously use my first option.
> >
> >> I still get errors pertaining to these lines. But after adding
> >> the -c to the two compilation lines in the script, these are
> >> now the only errors. I think I am getting closer. The errors
> >> are now
> >
> > Yes, you must compile it like this:
> >
> > g++ -c jband.cpp (for C++ code)
> > gcc -c jband.c (for C code)
> >
> > You don't need any -o but you could add in lots of warnings like
> >
> > gcc -Wall -Wextra -c jband.c
> >
> >> jband.cpp: In function 'void calledFromFortran()':
> >> jband.cpp:12:9: error: expected primary-expression before ':' token
> >> 12 | :
> >> | ^
> >> jband.cpp: At global scope:
> >> jband.cpp:96:1: error: expected initializer before 'extern'
> >> 96 | extern "C" {
> >> | ^~~~~~
> >> jband.cpp:104:1: error: expected unqualified-id before '{' token
> >> 104 | {
> >> | ^
> >> jbandtest.f90:28:14:
> >>
> >> 28 | FORTJBAND = JBAND (tbar)
> >> | 1
> >> Error: Type mismatch in argument 'tbar' at (1); passed REAL(16) to REAL(10)
> >>
> >> The last error will go away together with the others.
> >
> > Michael S has given you one way to go for that. My comments were going
> > to be more general. You have several ways of specifying the types, and
> > I could not tell if you really wanted all of them. In general, I would
> > define the Fortran types from the C ones (since those are the types you
> > need for the call and return) and leave it at that.
> >
> > But the big one is that the Fortran code seems to think the function is
> > called jband, when in fact it's called iband.
> >
> > I went for this:
> >
> > module STUFF
> > use iso_c_binding
> > integer, parameter :: qud=real(c_long_double)
> > end module STUFF
> > program JBAND_TEST
> > use STUFF; implicit none
> > real(qud) :: tbar, curr, FORTJBAND
> > do
> > read *, tbar
> > if (tbar < 0) exit
> > curr = FORTJBAND (tbar)
> > print '(" curr =", f10.4)', curr
> > enddo
> > end program JBAND_TEST
> >
> > function FORTJBAND (tbar)
> > use STUFF; implicit none
> > interface
> > function IBAND (tbar) bind(c)
> > use STUFF
> > real(qud), VALUE :: tbar
> > real(qud) :: IBAND
> > end function iband
> > end interface
> > real(qud) :: FORTJBAND, tbar
> > FORTJBAND = IBAND(tbar)
> > end function FORTJBAND
> >
> > Note that you can compile the Fortran along with the C at the same time
> > if you like:
> >
> > $ gfortran -o jtest jbandtest.f90 jband.c -lm
> > $ ./jtest
> > 1
> > curr = 1.5224
> > 1e-10
> > curr =56419.9584
> > -1
> > $
> >
> > ($ is my Linux command-line prompt). I have no idea if these are
> > correct results and I can't be sure what you need to run on your system,
> > but the code links and appears to work.
> >
> > If you go with the C++ option, the linking needs the standard C++
> > library:
> >
> > $ gfortran -o jtest jbandtest.f90 jband.cpp -lstdc++ -lm
> > $ ./jtest
> > 1
> > curr = 1.5224
> > 1e-10
> > curr =56419.9584
> > -1
> > $
> >
> > BTW, you said the C++ was written by a C++ expert. I don't think it
> > was!
> >
> The code, apart from the extra lines suggested by someone here,
> but without the information on where to put them, is runnable
> C++ code written by another person who knows C++ very well. I
> myself use Fortran and you are right, I know next to nothing
> about C++. I did use the extra code exactly as is, but possibly
> put it in the wrong place. I tried two, without success.
> I am giving up,

It seems to me, you are giving up too early.
If I guessed you original code correctly then all you have to do
on C++ side is to replace that line:
const long double iband(const long double tbar)
by that line:
extern "C" long double iband(const long double tbar)

> and will translate the C++ function into Fortran,
> where I know what I'm doing.

Understanding what you are doing is valuable, yes.

> --
> Dieter Britz

SubjectRepliesAuthor
o Problem with calling C++ from Fortran

By: db on Sat, 9 Sep 2023

31db
server_pubkey.txt

rocksolid light 0.9.81
clearnet tor