c++ calling fortran and fortran calling C++ 
Author Message
 c++ calling fortran and fortran calling C++

Hi,
For my application in C++, I need to call a subtroutine in fortran.
This subroutine must call a function of my program. I'm trying to use
pointer of my function but I have segmentation fault.

the fortran code is:

subroutine dlltest [dllexport] (c_msg,e1,e2,e3,i,r,d,str)
c
        implicit none

        integer i,l,m,length
        real*4 r
        double precision d
        character*128 e1,e2,e3,str,aux,aux2
        external c_msg,length

c  first, write parameters to a file

        open(1,file='test.out',status='unknown')
        rewind(1)
c       write(1,*) 'function pointer: ',c_msg
        write(1,*) 'integer:          ',i
        write(1,*) 'real:             ',r
        write(1,*) 'double precision: ',d
        write(1,4) str(1:length(str))
4       format('string:           "',(a),'"')
        close(1)

c  next, pass the received parameters to the external subroutine

        write(aux,*) i
        l=length(aux)
        write(aux2,*) r
        m=length(aux2)
        write(e1,1) aux(1:l),aux2(1:m)                          ! e1 = i & r
1       format('integer: ',(a),',   real: ',(a))
        write(aux,*) d
        l=length(aux)
        write(e2,2) aux(1:l)                                            ! e2 = d
2       format('double precision: ',(a))
        write(e3,3) str(1:length(str))                          ! e3 = str
3       format('string: "',(a),'"')

        call c_msg(e1,e2,e3)

        return
        end

        integer function length(str)
c
c  this function returns the length of a string as the
c  number of non-space characters (embedded spaces are
c  allowed) and shifts the characters to the leftmost
c  edge of the string, filling the rest of it with spaces.
c
        implicit none

        integer i,j,k,l,m
        character*(*) str
        character*1 tab
        tab=char(9)
        k=len(str)
        do j=k,1,-1
          if(str(j:j).ne.' '.and.str(j:j).ne.tab) goto 1
          continue
        end do
        length=0
        return
1       do i=1,j
          if(str(i:i).ne.' '.and.str(i:i).ne.tab) goto 2
          continue
        end do
2       length=j-i+1
        if(i.eq.1) return
        m=1
        do l=i,j
          str(m:m)=str(l:l)
          m=m+1
        end do
          str(m:k)=' '
        return
        end

In my application(wxwidgets) I use somethings like this:

    - First I define a function
   void  MaFonction( const char* e1,const char* e2,const char* e3 )
{
....

Quote:
}

    - I define a pointer

typedef void (*c_msg)(const char * ,const char* ,const char* );
c_msg essaip = &MaFonction;

  - I call my dll

typedef void (*inti)(c_msg ,const char*,const char *,const char *,long
*, float*,double*,const char*);
inti pint;
pint = (inti) wxDllLoader::GetSymbol(mydll,"DLLTEST");
....
 pint(essaip,mystring,mystring,mystring,&a,&b,&c,mystring);

I have a segmentation fault and I don't know where is the problem.

thanks for you help



Sat, 28 Oct 2006 23:59:10 GMT  
 c++ calling fortran and fortran calling C++
rom (aka Bruce) was almost, but not quite, entirely unlike tea:

Quote:
> Hi,
> For my application in C++, I need to call a subtroutine in fortran.
> This subroutine must call a function of my program. I'm trying to use
> pointer of my function but I have segmentation fault.
...
>     - First I define a function
>    void  MaFonction( const char* e1,const char* e2,const char* e3 )
> {

I'm going to soon use a C++ function from fortran, so I think I have
partly figured out what's needed for that direction -- perhaps it is
also applicable in the other direction (what you need). Since you are
dealing with DLLs on some windows emulator, I probably have aboslutely
no idea :)

First, the calling conventions and properties of character arrays,
etc, between C and fortran are very different. And C++ and C differ
(at link time).

Maybe start at (for fortran->C)
http://hpcf.nersc.gov/software/ibm/c_and_f.html
http://owen.sj.ca.us/rkowen/howto/FandC/FandC.call.html

In in the C++ case, what you will have to do, is in the C++ file, put
in your header file:

extern "C" {
   void cMyFortranFunction(blah...)

Quote:
}

write a function cMyFortranFunction(blah...) which is then in "c
mode", and can call fortran code using the usual method for mixing C
and fortran (eg, passing by reference, add an underscore to the
fortran subroutine name, pass lengths of character arrays as silent
last arguments (by value) etc).

Calling C++ from fortran is done similarly: from fortran, call a
cMyCFuction, which is a function prototyped with 'extern "C"', and
then it can call the C++ function (this convoluting is necessary,
because C++ has function overloading, the the real name is mangled in
a way that only your c++ compiler will know about -- but it still
should work because you are still compiling your 'extern "C"' function
with the C++ compilre)

I have no idea where your segfaul is coming from, but it could well be
related to the current "Illegal instruction (core dumped)" thread
going on - you are interepreting your paramaters wrong (remeber, C
passes by value, fortran by reference), or trying to execute data as
code, or maybe deferencing a null, etc.

--
TimC -- http://astronomy.swin.edu.au/staff/tconnors/
I repeat myself when under stress. I repeat myself when under
stress. I repeat myself when under stress. I repeat myself when
under stress. I repeat myself when under stress. I repeat myself
when under stress. I repeat myself when under stress. I repeat



Sun, 29 Oct 2006 09:22:04 GMT  
 c++ calling fortran and fortran calling C++


Quote:
>Hi,
>For my application in C++, I need to call a subtroutine in fortran.
>This subroutine must call a function of my program. I'm trying to use
>pointer of my function but I have segmentation fault.

You don't say what compilers you're using but under Windows every
Fortran compiler I've used also passes a hidden argument for each
character argument giving its length. Sometimes this is straight after
each character argument, sometimes at the end of the list and sometimes
they are passed by value. You'll need to look up your compiler
documentation on this one.

Also you need to make sure that your function is using the same calling
convention as your C++ app uses internally. It's possible that this is
not the same calling convention that it is using when calling the DLL
routine.

Catherine.

Quote:

>the fortran code is:

>subroutine dlltest [dllexport] (c_msg,e1,e2,e3,i,r,d,str)
>c
>       implicit none

>       integer i,l,m,length
>       real*4 r
>       double precision d
>       character*128 e1,e2,e3,str,aux,aux2
>       external c_msg,length

>c  first, write parameters to a file

>       open(1,file='test.out',status='unknown')
>       rewind(1)
>c      write(1,*) 'function pointer: ',c_msg
>       write(1,*) 'integer:          ',i
>       write(1,*) 'real:             ',r
>       write(1,*) 'double precision: ',d
>       write(1,4) str(1:length(str))
>4      format('string:           "',(a),'"')
>       close(1)

>c  next, pass the received parameters to the external subroutine

>       write(aux,*) i
>       l=length(aux)
>       write(aux2,*) r
>       m=length(aux2)
>       write(e1,1) aux(1:l),aux2(1:m)                          ! e1 = i & r
>1      format('integer: ',(a),',   real: ',(a))
>       write(aux,*) d
>       l=length(aux)
>       write(e2,2) aux(1:l)                                            ! e2 = d
>2      format('double precision: ',(a))
>       write(e3,3) str(1:length(str))                          ! e3 = str
>3      format('string: "',(a),'"')

>       call c_msg(e1,e2,e3)

>       return
>       end

>       integer function length(str)
>c
>c  this function returns the length of a string as the
>c  number of non-space characters (embedded spaces are
>c  allowed) and shifts the characters to the leftmost
>c  edge of the string, filling the rest of it with spaces.
>c
>       implicit none

>       integer i,j,k,l,m
>       character*(*) str
>       character*1 tab
>       tab=char(9)
>       k=len(str)
>       do j=k,1,-1
>         if(str(j:j).ne.' '.and.str(j:j).ne.tab) goto 1
>         continue
>       end do
>       length=0
>       return
>1      do i=1,j
>         if(str(i:i).ne.' '.and.str(i:i).ne.tab) goto 2
>         continue
>       end do
>2      length=j-i+1
>       if(i.eq.1) return
>       m=1
>       do l=i,j
>         str(m:m)=str(l:l)
>         m=m+1
>       end do
>         str(m:k)=' '
>       return
>       end

>In my application(wxwidgets) I use somethings like this:

>    - First I define a function
>   void  MaFonction( const char* e1,const char* e2,const char* e3 )
>{
>....
>}

>    - I define a pointer

>typedef void (*c_msg)(const char * ,const char* ,const char* );
>c_msg essaip = &MaFonction;

>  - I call my dll

>typedef void (*inti)(c_msg ,const char*,const char *,const char *,long
>*, float*,double*,const char*);
>inti pint;
>pint = (inti) wxDllLoader::GetSymbol(mydll,"DLLTEST");
>....
> pint(essaip,mystring,mystring,mystring,&a,&b,&c,mystring);

>I have a segmentation fault and I don't know where is the problem.

>thanks for you help

--
Catherine Rees Lay
To email me, use my first name in front of the "at".


Sun, 29 Oct 2006 16:47:02 GMT  
 c++ calling fortran and fortran calling C++
thanks for your answer.

I don't know wich compilater was used for the fortran dll. I just develop
an IHM and I must use a dll in fortran for calculation.

Currently, I do some test with mixing fortran and C++. I have another dll
wich accept a real,a long,a string , and which return a file with this
values.
I call this dll from my application in C++ and all is ok.

But now, I try to use the dll in the first post and I have some
difficulty.



Sun, 29 Oct 2006 21:17:58 GMT  
 c++ calling fortran and fortran calling C++
| thanks for your answer.
|
| I don't know wich compilater was used for the fortran dll. I just develop
| an IHM and I must use a dll in fortran for calculation.

Now, that could be a problem...

subroutine dlltest [dllexport] (c_msg,e1,e2,e3,i,r,d,str)

This syntax indicates that this is one of:

1) Microsoft PowerStation 4.0
2) Digital/Compaq visual fortran 5.0-6.6
3) Intel [Visual] Fortran 7 or 8

if the dll is dynamically linked with Fortran run-time library,
you can deduce what it is by seeing its dependencies. If you have
MS Visual C++, there's a tool "Dependency walker" (Depends) in its
program group. You can freely download it from www.dependencywalker.com.

Next, open the dll from Dependency Walker and you will see in
upper left pane its dependencies (normally, Kernel32.dll at least).
If there's a "DFORRT*.dll" as well, it's 2) -- Compaq Visual Fortran.
If "IF***.dll", it's 3). If none, well, that means it's statically
linked.

In the middle right pane, you will see dll exported functions. What's
the exact name (case matters) for dlltest?

| Currently, I do some test with mixing fortran and C++. I have another dll
| wich accept a real,a long,a string , and which return a file with this
| values.
| I call this dll from my application in C++ and all is ok.

Second, fortran string arguments are always passed with hidden length argument.
E.g.

subroutine foo(s, i)
character(*):: s
integer::      i

has C equivalent which is one of:

void foo(char* s, int s_len, int* i)  // CVF/FPS default
void foo(char* s, int* i, int s_len)  // IVF default

i.e. either immediately following string argument, or at the end of
argument-list.

Third, calling convention matters. CVF/FPS use __stdcall, while
IVF uses __cdecl. __stdcall symbols are by default exported as

as "_FOO". However, the function can be renamed on export, so you
cannot be sure. Failure to match the calling convention can lead
either to link errors or ugly "fandango on stack" run-time
misbehaviours.

Note that all I said above are compiler default options -- they
might have been changed one way or another during dll compilation.

--
 Jugoslav
___________
www.geocities.com/jdujic

Please reply to the newsgroup.
You can find my real e-mail on my home page above.



Mon, 30 Oct 2006 17:16:43 GMT  
 c++ calling fortran and fortran calling C++
Thanks for your answers.

Cmpilater is visual fortran 5.
I did another test with a dll which call a C++ function but with an
interger,a real,a double for arguments and all is ok. Problem comes from
string. I have an access violation. I hope to solve this problem with your
advices.



Mon, 30 Oct 2006 17:47:53 GMT  
 c++ calling fortran and fortran calling C++
DFORRT.dll is present
there are two dll exported function:
DLLTEST



Mon, 30 Oct 2006 17:58:23 GMT  
 c++ calling fortran and fortran calling C++
| DFORRT.dll is present
| there are two dll exported function:
| DLLTEST

subroutine dlltest [dllexport] (c_msg,e1,e2,e3,i,r,d,str)
c
implicit none

integer i,l,m,length
real*4 r
double precision d
character*128 e1,e2,e3,str,aux,aux2

In this case, C prototype should be:

extern "C" __stdcall DLLTEST
(
  C_MSG,  //(typedef for external, or void*)
  char* e1,
  int e1_len,
  char* e2,
  int e2_len,
  char* e3,
  int e3_len,
  int& i,
  float& r,
  double& d,
  char* str,
  int str_len
)


C_MSG should be:

typedef C_MSG void (__stdcall)(char*, int, char*, int, char*, int)

(I doubt this is syntax correct declaration as I always forget correct C
typedefs to function, but you get the idea).

--
 Jugoslav
___________
www.geocities.com/jdujic

Please reply to the newsgroup.
You can find my real e-mail on my home page above.



Mon, 30 Oct 2006 18:34:05 GMT  
 c++ calling fortran and fortran calling C++
thank you very much
My program work now.

I used your advice. I add new fonction to have the whole string and it
seems to work.

extern "C" void  __stdcall MaFonction(char* st1, int st1_len, char* st2,
int st2_len,char* st3, int st3_len )
{
    char* str1=new char[st1_len+1];     // C++ memory allocation
    for (unsigned int i=0; i<st1_len; i++)
      str1[i]=st1[i];                   // strncpy is probably nicer here
    str1[st1_len]='\0';



Mon, 30 Oct 2006 21:57:57 GMT  
 c++ calling fortran and fortran calling C++
| thank you very much
| My program work now.
|
| I used your advice. I add new fonction to have the whole string and it
| seems to work.
|
| extern "C" void  __stdcall MaFonction(char* st1, int st1_len, char* st2,
| int st2_len,char* st3, int st3_len )
| {
|     char* str1=new char[st1_len+1]; // C++ memory allocation
|     for (unsigned int i=0; i<st1_len; i++)
|       str1[i]=st1[i]; // strncpy is probably nicer here
|     str1[st1_len]='\0';

I hope that delete[] str1; is within missing lines :-)

--
 Jugoslav
___________
www.geocities.com/jdujic

Please reply to the newsgroup.
You can find my real e-mail on my home page above.



Mon, 30 Oct 2006 22:54:09 GMT  
 
 [ 10 post ] 

 Relevant Pages 

1. C++ calling Fortran calling C++

2. VC++ calling fortran function and fortran function calling a c++ function

3. calling Visual C++ or Prolog calling Visual C++

4. Calling C++ objects from Fortran

5. calling C++ function from Fortran: parameter passing

6. How to call C++ function from Fortran 90

7. How to call Fortran moules from C++?

8. Calling C++ from Fortran

9. how to call c++ procedure from fortran

10. Calling ForTran routines from C++?

11. calling fortran from c++

12. call fortran subroutines from C++

 

 
Powered by phpBB® Forum Software