Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Problem using exported method via .obj file

Sorensen__Henrik
Beginner
1,142 Views

I have a dll project p1 that has a source file p1.for that exports one subroutine

SUBROUTINE P1()
      IMPLICIT DOUBLE PRECISION(A - H,O - Z)
      !DEC$ATTRIBUTES DLLEXPORT :: P1
      !DEC$ATTRIBUTES ALIAS:'P1' :: P1
      RETURN
END
   

After building, it will produce p1.dll, p1.lib and p1.obj.

Now I have another dll project p2, that has p1.obj as Additional Dependency.

In p2.for I make a call to P1().

For this I get a linker error 

error LNK2019: unresolved external symbol _p1 referenced in function _p2    p2.obj    

If I comment out the DLLEXPORT part in P1, the p2 project builds without errors.

 

Is this a feature, and how I can have P1 exposed from dll and also used via .OBJ file? One way is making a wrapper method P11() that would not be exported, and I would call that one from p2.

 

 

0 Kudos
1 Solution
IanH
Honored Contributor III
1,142 Views

You are using external procedures.  When compiling P2 the compiler has no idea what you may or may not have done inside P1.  The compiler doesn't know that you have changed aspects of the calling convention from their default using the compiler directives, and so it emits symbols for the linker to deal with that are inconsistent with the symbols emitted when P1 itself was compiled.

Inside P2 you need to tell the compiler about these non-default characteristics of P1 using an interface block.

If P1 was in a module then this would be handled for you via the information communicated through the USE statement.

View solution in original post

0 Kudos
5 Replies
mecej4
Honored Contributor III
1,142 Views

I suspect that you are mixing architectures and compilers. With the ALIAS directive removed, the decorated name placed by IFort in the .OBJ file is _P1 for 32-bit targets and P1 for 64-bit targets. If p2.f90 does not have any ALIAS directives, IFort would not have produced a reference to _p1 (note lowercase) in either 32-bit or 64-bit.

Secondly, if you do not link with the exports library p1.lib when building p2, whether the DLL exists or not should be of no consequence.

How do you build? What options are in effect? Do you use any nonstandard linker options?

0 Kudos
Sorensen__Henrik
Beginner
1,142 Views

As I mentioned, in the p2 project there is Additional Dependency p1.obj and that's all for the linker options.

p2.for does have ALIAS and DLLEXPORT, the same way p1.for has it in the sample code above.

I build the 32-bit version.

0 Kudos
mecej4
Honored Contributor III
1,142 Views

hs@calsep.com wrote:
p2.for does have ALIAS and DLLEXPORT, the same way p1.for has it in the sample code above.

That is ambiguous. The problem you described is about a name that p2 is supposed to import, not export. Please post more details such as the build logs or, better still, the cleaned project with all files zipped together.

Unless you have a /names:lowercase option or have 'p1' in lower case as an alias name, I don't think the linker should complain about not finding _p1.

0 Kudos
Sorensen__Henrik
Beginner
1,142 Views

Hi,

Sorry for the delay, but here is the sample project file.

In the P1.for if you comment out the two lines with DLLEXPORT and ALIAS, the and rebuild Dll1 and Dll2, everything works.

But if these lines are not commented out, then rebuild Dll1 and Dll2, you'll see the errors when building Dll2.

0 Kudos
IanH
Honored Contributor III
1,143 Views

You are using external procedures.  When compiling P2 the compiler has no idea what you may or may not have done inside P1.  The compiler doesn't know that you have changed aspects of the calling convention from their default using the compiler directives, and so it emits symbols for the linker to deal with that are inconsistent with the symbols emitted when P1 itself was compiled.

Inside P2 you need to tell the compiler about these non-default characteristics of P1 using an interface block.

If P1 was in a module then this would be handled for you via the information communicated through the USE statement.

0 Kudos
Reply