By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,563 Members | 1,307 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,563 IT Pros & Developers. It's quick & easy.

Passing address of a C++ function to Fortran - syntax??

P: n/a
I am trying to pass the address of a C++ function into a Fortran
routine to enable the Fortran routine to call this C++ function. I
have to do it this way as our build process does not allow circular
dependencies of DLL's.

Does anyone know how to do this, I have tried everything in my book.

I have a C++ function GetP:

DllExport void GetP()
{
...code...
return;
}

I am trying to pass the address of this function into a Fortran
routine called BIND_FTN. The call is made from another area of the
C++ code as follows:

void (GetP)();
DllImport void __stdcall BIND_FTN(int* GetP);

void Initialize()
{
...code...
BIND_FTN(GetP); // inform Fortran of address of callback
function
return;
}

The C++ will not compile, I get:
error C2664: 'BIND_FTN' : cannot convert parameter 1 from 'void
(__cdecl *)(void)' to 'int *'

Can anyone see the problem here?

Here is the Fortran code for BIND_FTN:

subroutine BIND_FTN_EXTERNALS[DLLEXPORT](ext)
external ext

interface
subroutine cb_GetP()
!DEC$ ATTRIBUTES STDCALL :: cb_GetP
end subroutine cb_GetP
end interface

pointer (p_GetP, cb_GetP)
p_GetP = loc(ext)

call cb_GetP ! call the C++ function from Fortran

return
end

(I haven't got to the Fortran yet - there may be syntax errors in
there)

Adrian
Jul 22 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Adrian,

Adrian wrote:
I am trying to pass the address of a C++ function into a Fortran
routine to enable the Fortran routine to call this C++ function. I
have to do it this way as our build process does not allow circular
dependencies of DLL's.

Does anyone know how to do this, I have tried everything in my book.


Well, last time I did this with a C function calling a C++ library
function, I had to write a wrapper interface for the C++ which performed
any object initialization & type conversions. In addition to this
requirement, you also needed to mark the wrapper interface in an extern
"C"{} block in order that the linker be able to deal with the two
differing languages.

Evan
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFBo/s8pxCQXwV2bJARAt/2AJ9zSVfV4gc8dZH1zSayPa1zOwC4dgCfceHG
i9xCYAuLURLqt7Id4dVMrkM=
=Xiu3
-----END PGP SIGNATURE-----
Jul 22 '05 #2

P: n/a
Adrian wrote:
I am trying to pass the address of a C++ function into a Fortran
routine to enable the Fortran routine to call this C++ function. I
have to do it this way as our build process does not allow circular
dependencies of DLL's. Does anyone know how to do this, I have tried everything in my book.


I would first learn how to call C++ from Fortran, though I
believe that it is best to call C from Fortran and C++ from C.

If you can call C or C++ from Fortran then I wouldn't expect
passing the address to be too hard. I would look at the
calling convention for both, but C can pass function addresses,
and so can Fortran. There aren't so many ways to do it.

I do suggest a C intermediate, though.

-- glen

Jul 22 '05 #3

P: n/a
Adrian wrote:
| I am trying to pass the address of a C++ function into a Fortran
| routine to enable the Fortran routine to call this C++ function. I
| have to do it this way as our build process does not allow circular
| dependencies of DLL's.
|
| Does anyone know how to do this, I have tried everything in my book.
|
| I have a C++ function GetP:
|
| DllExport void GetP()
| {
| ...code...
| return;
| }
|
| I am trying to pass the address of this function into a Fortran
| routine called BIND_FTN. The call is made from another area of the
| C++ code as follows:
|
| void (GetP)();
| DllImport void __stdcall BIND_FTN(int* GetP);
|
| void Initialize()
| {
| ...code...
| BIND_FTN(GetP); // inform Fortran of address of callback
| function
| return;
| }
|
| The C++ will not compile, I get:
| error C2664: 'BIND_FTN' : cannot convert parameter 1 from 'void
| (__cdecl *)(void)' to 'int *'
|
| Can anyone see the problem here?

You're passing a function as the actual argument, but the declaration
says it should be an int*. Obviously, the declaration is wrong. You
need either void* and cast GetP in the call to void*, or, more nice,
spell it out:

typedef void __stdcall GETP(void);

DllImport void __stdcall BIND_FTN(GETP);

| Here is the Fortran code for BIND_FTN:
|
| subroutine BIND_FTN_EXTERNALS[DLLEXPORT](ext)
| external ext
|
| interface
| subroutine cb_GetP()
| !DEC$ ATTRIBUTES STDCALL :: cb_GetP
| end subroutine cb_GetP
| end interface
|
| pointer (p_GetP, cb_GetP)
| p_GetP = loc(ext)
|
| call cb_GetP ! call the C++ function from Fortran
|
| return
| end

No need to use Cray pointers here. Instead, just declare the argument
as external and spell out its interface:

subroutine BIND_FTN_EXTERNALS(cb_GetP)
!DEC$ATTRIBUTES DLLEXPORT:: BIND_FTN_EXTERNALS

interface
subroutine cb_GetP()
!DEC$ ATTRIBUTES STDCALL :: cb_GetP
end subroutine cb_GetP
end interface

call cb_GetP ! call the C++ function from Fortran

return
end

Here's the complete working C++ code:

#include "stdafx.h"
#include <stdio.h>

#define FORTRAN_DLL_CALL __stdcall

typedef void __stdcall GETP(void);
void __stdcall GetP(void);
extern "C" void FORTRAN_DLL_CALL BIND_FTN_EXTERNALS(GETP);

int main(int argc, char* argv[])
{
BIND_FTN_EXTERNALS(GetP); // inform Fortran of address of callback
return 0;
}

void __stdcall GetP(void)
{
printf("Hello World");
}
--
Jugoslav
___________
www.geocities.com/jdujic

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

Jul 22 '05 #4

P: n/a
Richard E Maine wrote:

(snip)
I do suggest a C intermediate, though.
Not that I've done scarecely any C++ interfacing myself, but my
understanding, from here and elsewhere, is that the biggest "trick" of
calling C++ from C is to make sure that the C++ routine is
defined with "extern C" (exact syntax might not be right, but
something like that). Once the C++ routine is callable from C, then it essentially is a
C routine, so no further intermediary is needed unless there are
independent reasons for one.


OK, I agree with this one. I thought it was calling an existing
C++ library (or DLL) function, but maybe not.

(snip)

-- glen

Jul 22 '05 #5

P: n/a
It sounds like you want to pass a function pointer from C/C++ to a Fortran
code. The Fortran code then calls the C/C++ function from a Fortran routine.

In general there are two things to consider. (1) naming conventions or
function decoration and (2) calling conventions. The function decoration is
highly dependent on the specific compilers that are being used. As far as
calling conventions are concerned the call into Fortran will require using
the standard call mechanism. The call from a Fortran External function will
use the C calling convention.

The function pointer can be passed as a void* from C/C++. If you want type
checking it can be defined differently.

I would be happy to help you with the details if you contact me at
Da***********@AdsorptionProcessModeling.com
"Adrian" <ac***@hotmail.com> wrote in message
news:6f**************************@posting.google.c om...
I am trying to pass the address of a C++ function into a Fortran
routine to enable the Fortran routine to call this C++ function. I
have to do it this way as our build process does not allow circular
dependencies of DLL's.

Does anyone know how to do this, I have tried everything in my book.

I have a C++ function GetP:

DllExport void GetP()
{
...code...
return;
}

I am trying to pass the address of this function into a Fortran
routine called BIND_FTN. The call is made from another area of the
C++ code as follows:

void (GetP)();
DllImport void __stdcall BIND_FTN(int* GetP);

void Initialize()
{
...code...
BIND_FTN(GetP); // inform Fortran of address of callback
function
return;
}

The C++ will not compile, I get:
error C2664: 'BIND_FTN' : cannot convert parameter 1 from 'void
(__cdecl *)(void)' to 'int *'

Can anyone see the problem here?

Here is the Fortran code for BIND_FTN:

subroutine BIND_FTN_EXTERNALS[DLLEXPORT](ext)
external ext

interface
subroutine cb_GetP()
!DEC$ ATTRIBUTES STDCALL :: cb_GetP
end subroutine cb_GetP
end interface

pointer (p_GetP, cb_GetP)
p_GetP = loc(ext)

call cb_GetP ! call the C++ function from Fortran

return
end

(I haven't got to the Fortran yet - there may be syntax errors in
there)

Adrian

Jul 22 '05 #6

P: n/a

"Jugoslav Dujic" <jd****@yahoo.com> wrote in message
news:30*************@uni-berlin.de...

[...]

You're undoubtedly aware that you can omit the DLLEXPORT metacommand in the
Fortran code and make the sample a straightforward mixed language one
instead of having to create a Fortran DLL.
--
Ciao,
Gerry T.
______
"Today's C++ programs will be tomorrow's unmaintainable legacy code." --Ian
Joyner, in a Critique of C++, 3rd ed., 1996.
Jul 22 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.