Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
29285 Discussions

Calling C++ from Fortran: Access Violations

Aaron_S_1
Beginner
1,198 Views

I've been trying to port some CVF code to Intel Fortran and I ran into the same problem that was solved at: http://software.intel.com/en-us/forums/topic/279785

I attempted to implement the solution Steve posted, but I am getting accesss violation errors.

In my Interface I have:

MODULE SERVICE_INTERFACE
IMPLICIT NONE

INTERFACE

SUBROUTINE saveResult(ARGS)

!DEC$ ATTRIBUTES DLLIMPORT,STDCALL :: saveResult

!DEC$ ATTRIBUTES DECORATE, ALIAS:'saveResult' :: saveResult

!DEC$ ATTRIBUTES REFERENCE :: ARGS

END SUBROUTINE saveResult

END INTERFACE

END MODULE SERVICE_INTERFACE

And in my subroutine I have:
INTEGER(handle) :: P
INTEGER(C_INTPTR_T) :: q1

P = loadlibrary("Service.dll"C)
IF(P == 0) THEN !Error Processing

q1 = getprocaddress(P,"_saveResult@4"C)
if(q1 == 0)then !Error Processing

CALL C_F_PROCPOINTER(TRANSFER(q1,C_NULL_FUNPTR), saveResult)

CALL saveResult(ARGS)

I don't have the option to recompile the C++, but that's not the issue because this worked in CVF. How can I make the call work? Also, does anyone have any suggestion on how I can replace the ATTRIBUTES in the interfaces with the BIND() function? I can't make the linker work using BIND().

0 Kudos
7 Replies
Aaron_S_1
Beginner
1,198 Views

By the way, I am using Intel Visual Fortran Composer XE 2013 Update 2

0 Kudos
Steven_L_Intel1
Employee
1,198 Views

You're missing some code from your excerpt here.  How is SaveResult declared in the subroutine? In the subroutine, you need to declare a procedure pointer to be used in the call to C_F_PROCPOINTER, and it has to be declared as having the interface you defined in the module. Practically speaking, these can't have the same name.

Can you work up a complete example that demonstrates the problem?  Provide a dummy C++ routine it uses. There's too much missing from your post to help you.

As for your question on BIND(C), sorry, you can't use that right now to call a STDCALL routine.

0 Kudos
Aaron_S_1
Beginner
1,198 Views

My source code was missing the procedure pointer. Now I have:

[fortran]

MODULE SERVICE_INTERFACE

IMPLICT NONE

INTERFACE

SUBROUTINE saveResult(ARGS) BIND(C, NAME='saveResult')

!DEC$ ATTRIBUTES REFERENCE :: ARGS

END SUBROUTINE saveResult

END INTERFACE

END MODULE SERVICE_INTERFACE

[/fortran]

The subroutine has been changed to:

[fortran]

INTEGER(handle) :: P

INTEGER(C_INTPTR_T) :: q1

procedure(saveResult), pointer :: saveResult_callback

P = loadlibrary("Service.dll"C)

q1 = getprocaddress(P,"_saveresult@4"C)

CALL C_F_PROCPOINTER(TRANSFER(q1, C_NULL_FUNPTR), saveResult_callback)

CALL saveResult_callback(ARGS)

[/fortran]

This compiles and calls into the C++ dll correctly. I'm only concerned about still loading the process with the @n suffix, but using only saveResults in the BIND call.

0 Kudos
Aaron_S_1
Beginner
1,198 Views

Sorry I can't come up with a more detailed example, I'm not allowed to have any c++ compilers on the machine I use for development and I don't know too much about the language.

0 Kudos
Steven_L_Intel1
Employee
1,198 Views

This latest version will appear to work, but will corrupt the stack.  Don't do it. The routine name from the interface is not used in the program you show here, but that the interface specifies the C convention and your routine is STDCALL will cause the stack to be double-popped on each call.  Very bad things will happen in a real program that does this - you may not notice in a toy program.

As I wrote earlier, you cannot use BIND(C) here - you must use the ATTRIBUTES STDCALL, REFERENCE.  The ALIAS and DECORATE can be removed as you're not using the name.

0 Kudos
Steven_L_Intel1
Employee
1,198 Views

Do you really need to use LoadLibrary here?  Is there not an export library (.lib) from the DLL you can link against?

0 Kudos
Aaron_S_1
Beginner
1,198 Views

I changed my code to get rid of the BIND statement and use the attributes.

I'm actually loading several different libraries, some have .lib files, some don't. I'm guessing it's easier to just link against these. I'll have to explore that option. Thanks for your responses. I really appreciate the help.

0 Kudos
Reply