Rocksolid Light

Welcome to RetroBBS

mail  files  register  newsreader  groups  login

Message-ID:  

"Free markets select for winning solutions." -- Eric S. Raymond


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

Re: Problem with calling C++ from Fortran

<udp8l4$1frsv$1@dont-email.me>

  copy mid

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

  copy link   Newsgroups: comp.lang.c++
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: dieterhansbritz@gmail.com (db)
Newsgroups: comp.lang.c++
Subject: Re: Problem with calling C++ from Fortran
Date: Tue, 12 Sep 2023 10:48:36 +0200
Organization: A noiseless patient Spider
Lines: 233
Message-ID: <udp8l4$1frsv$1@dont-email.me>
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>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Tue, 12 Sep 2023 08:48:36 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="a95eb3e5ffa1773c6f3000948b8740fd";
logging-data="1568671"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/cvnaedVKUGz09MGxbSB99TZMAz1+2FyI="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101
Thunderbird/102.15.0
Cancel-Lock: sha1:PyQxj+B6BQ0toPHSHuO0tbwcrgs=
Content-Language: en-US
In-Reply-To: <87cyyoqoka.fsf@bsb.me.uk>
 by: db - Tue, 12 Sep 2023 08:48 UTC

On 12.09.2023 01.26, Ben Bacarisse wrote:
> db <dieterhansbritz@gmail.com> writes:
>
>> On 10.09.2023 15.22, Ben Bacarisse wrote:
>>> db <dieterhansbritz@gmail.com> writes:
>>>
>>>> On 09.09.2023 11.02, Muttley@dastardlyhq.com wrote:
>>>>> On Sat, 9 Sep 2023 10:54:33 +0200
>>>>> db <dieterhansbritz@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, and will translate the C++ function into Fortran,
where I know what I'm doing.
--
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