首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >混合编程:从C++调用FORTRAN

混合编程:从C++调用FORTRAN
EN

Stack Overflow用户
提问于 2014-11-28 05:04:23
回答 1查看 2K关注 0票数 1

我正在尝试用命令行编译一个混合程序。

编译工具是intel visual fortran 2013和VS 2013。

我搜索了一下,发现使用dll比使用lib更容易。

因此,我试图将fortran源代码编译为dll文件。

我的Fortran消息来源:

代码语言:javascript
运行
复制
!  forsubs.f90 
!
!  FUNCTIONS/SUBROUTINES exported from FORSUBS.dll:
! FORSUBS      - subroutine 
!
INTEGER*4 FUNCTION Fact (n)
   !DEC$ ATTRIBUTES DLLEXPORT::Fact
      INTEGER*4 n [VALUE]
      INTEGER*4 i, amt
      amt = 1
      DO i = 1, n
        amt = amt * i
      END DO
      Fact = amt
   write(*,*)"Mixed calls succeed!"
END
SUBROUTINE Pythagoras (a, b, c)
   !DEC$ ATTRIBUTES DLLEXPORT::Pythagoras
      REAL*4 a [VALUE]
      REAL*4 b [VALUE]
      REAL*4 c [REFERENCE]
      c = SQRT (a * a + b * b)
END

我的C++来源: c_main.cpp

代码语言:javascript
运行
复制
/*     File CMAIN.C   */

#include <stdio.h>

extern int __stdcall fact(int* n);
extern void __stdcall pythagoras(float* a, float* b, float *c);

int main()
{
    float c;
    printf("Factorial of 7 is: %d\n", FACT(7));
    PYTHAGORAS (30, 40, &c);
    printf("Hypotenuse if sides 30, 40 is: %f\n", c);
}

首先,我编译了我的fortran源代码:

/dll forsubs.f90

得到一个forsubs.dll和一个forsubs.lib

第二,我编译了我的C++源代码:

cl c_main.cpp /link forsubs.lib

但是,我得到了一个错误:

代码语言:javascript
运行
复制
D:\c_f\c_f_dll\c_main.cpp(11) : error C3861: “FACT”:  identifier not found
D:\c_f\c_f_dll\c_main.cpp(12) : error C3861: “PYTHAGORAS”:  identifier not found

此外,我还尝试以另一种方式加载dll,方法是:

代码语言:javascript
运行
复制
 HINSTANCE hLibrary=LoadLibrary("forsubs.dll"); 
 if(hLibrary==NULL)
 {
  cout<<"can't find the dll file"<<endl;
  return -1;
 }

但是每次我都有一个“找不到dll文件”,而我确信forsubs.dll在文件夹中。

我不擅长C++,无法找到如何编译它,帮助!

编辑

奇怪!我把我的程序编辑为@的答案,但仍然有一个错误。

代码语言:javascript
运行
复制
error LNK2019: unresolved external symbol _FACT@4 referenced in function _main
error LNK2019: unresolved external symbol _PYTHAGORAS@12 referenced in function _main

此外,我搜索了一下,有人说__stdcall不是必要的,我删除了,但仍然有错误:

代码语言:javascript
运行
复制
error LNK2019: unresolved external symbol _FACT referenced in function _main
error LNK2019: unresolved external symbol _PYTHAGORAS referenced in function _main

我想这可能是和this一样的问题。但不能靠自己解决。

PS:我的dlllib信息

代码语言:javascript
运行
复制
D:\c_f\c_f_dll>dumpbin /exports forsubs.lib
Microsoft (R) COFF/PE Dumper Version 12.00.30501.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file forsubs.lib

File Type: LIBRARY

     Exports

       ordinal    name

                  FACT
                  PYTHAGORAS

  Summary

          C3 .debug$S
          14 .idata$2
          14 .idata$3
           8 .idata$4
           8 .idata$5
           C .idata$6

D:\c_f\c_f_dll>dumpbin /exports forsubs.dll
Microsoft (R) COFF/PE Dumper Version 12.00.30501.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file forsubs.dll

File Type: DLL

  Section contains the following exports for forsubs.dll

    00000000 characteristics
    5477F1C5 time date stamp Fri Nov 28 11:53:41 2014
        0.00 version
           1 ordinal base
           2 number of functions
           2 number of names

    ordinal hint RVA      name

          1    0 00001000 FACT
          2    1 000010B0 PYTHAGORAS

  Summary

        1000 .data
        1000 .pdata
        1000 .rdata
        1000 .reloc
        1000 .text

Edit2

代码语言:javascript
运行
复制
Also, I have tried to add a header:
#ifdef FORSUBS_EXPORTS
#define FORSUBS_API __declspec(dllexport) 
#else
#define FORSUBS_API __declspec(dllimport) 
#endif

但还是不管用。

EN

回答 1

Stack Overflow用户

发布于 2014-11-28 06:11:23

C/C++区分大小写,所以如果调用FACT,则必须将其声明为FACT,而不是fact。或者是另一个方向。

并且您需要声明您的函数(在C++代码中)为extern "C",以禁用为C++特定的名称-mangling,否则将被假定为。

__stdcall确实是Fortran函数的正确调用约定(默认情况下)。

Fortran不区分大小写(默认情况下,它可以通过编译器选项进行更改,这是愚蠢的)。我相信Intel Fortran编译器为Fortran函数生成所有大写符号(用于链接目的)(例如,名为“事实”的函数将被导出为“事实”)。因此,您需要在C++声明中匹配这种情况。我不确定它与Fortran符号(全大写还是全小写)的匹配方式,所以,如果其中一个不能工作,就试试另一个。

编辑2:

至于原型,我相信这是C++中正确的形式(我不确定,因为对于Fortran,我很生疏):

代码语言:javascript
运行
复制
#include <stdint.h>  // in C, or <cstdint> in C++ (but must use std::int32_t)

extern "C" __declspec(dllimport) int32_t __stdcall FACT(int32_t n);
extern "C" __declspec(dllimport) void __stdcall PYTHAGORAS(float a, float b, float *c);

注意,对于一个4字节的整数,您需要使用int32_t,对于Fortran中的[VALUE]类型,它也应该在C/C++中通过值传递.至少,这是我对它的理解(但就像我说的,我不是Fortran专家)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27182209

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档