Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用c+创建.lib文件+;和Fortran/callc++;来自Fortran的代码/未解析的外部符号_C++_Fortran_Object Files_Psse - Fatal编程技术网

C++ 使用c+创建.lib文件+;和Fortran/callc++;来自Fortran的代码/未解析的外部符号

C++ 使用c+创建.lib文件+;和Fortran/callc++;来自Fortran的代码/未解析的外部符号,c++,fortran,object-files,psse,C++,Fortran,Object Files,Psse,我试图创建一个包含C++函数的fortran函数的.LB库文件,但是我得到了可怕的“错误LNK2019:未解析的外部符号……”。该代码最终将与其他库一起编译为DLL,并在单独的程序(PSSE)中使用。当PSSE试图使用我的库创建DLL时,我遇到编译错误。下面是我试图使用的代码,后面是编译代码。代码只需将两个数字相加并输出答案 福特代码 SUBROUTINE TESTCPP ( II, JJ, KK, LL ) INCLUDE 'COMON4.INS' integer*4, exte

我试图创建一个包含C++函数的fortran函数的.LB库文件,但是我得到了可怕的“错误LNK2019:未解析的外部符号……”。该代码最终将与其他库一起编译为DLL,并在单独的程序(PSSE)中使用。当PSSE试图使用我的库创建DLL时,我遇到编译错误。下面是我试图使用的代码,后面是编译代码。代码只需将两个数字相加并输出答案

福特代码

  SUBROUTINE TESTCPP ( II, JJ, KK, LL )
  INCLUDE 'COMON4.INS'

  integer*4, external :: CPPFUNCTION

  INTEGER a, b, c, test

  IF (.NOT. IFLAG) RETURN

  a = ICON(II)
  b = ICON(II + 1)
  test = CPPFUNCTION( a , b, c )
  WRITE ( ITERM, * ) 'C = ', c
  RETURN
  END
cpp_代码.cpp

extern "C" {
      void _CPPFUNCTION(int a, int b, int *c);
}

void _CPPFUNCTION(int a, int b, int *c) {
      *c = a + b;
    }
编译.bat

cl /nologo /MD /c /W3 /O2 /FD /EHsc /errorReport:prompt /D"MSWINDOWS" /D"WIN32" ^
   /D"_WINDOWS" /D"NDEBUG" "cpp_code.cpp"

IFORT /nologo /Od /Oy- /assume:buffered_io /traceback /libs:dll /threads /c /Qip ^
      /extend_source:132 /noaltparam /fpscomp:logicals /warn:nodeclarations ^
      /warn:unused /warn:truncated_source /Qauto /Op /iface:cvf /define:DLLI ^
      /include:"C:\Program Files (x86)\PTI\PSSE32\PSSLIB" ^
      /object:"fort_code.OBJ" ^
      "fort_code.f" 

lib /out:fort_cpp.lib fort_code.obj cpp_code.obj
当PSSE程序尝试创建DLL时,我得到的输出是:

 ifort /nologo /assume:buffered_io /traceback /libs:dll /threads /c /Qip /extend_source:132 /noaltparam /fpscomp:logicals /Qprec /warn:declarations /warn:unused /warn:truncated_source /Qauto /fp:source /iface:cvf /define:DLLI /include:"C:\Program Files (x86)\PTI\PSSE32\PSSLIB" /object:"C:\temp\INIT_620289\11hw2ap_conec.obj" /module:"C:\temp\INIT_620289" "11hw2ap_conec.f"


 ifort /nologo /assume:buffered_io /traceback /libs:dll /threads /c /Qip /extend_source:132 /noaltparam /fpscomp:logicals /Qprec /warn:declarations /warn:unused /warn:truncated_source /Qauto /fp:source /iface:cvf /define:DLLI /include:"C:\Program Files (x86)\PTI\PSSE32\PSSLIB" /object:"C:\temp\INIT_620289\11hw2ap_conet.obj" /module:"C:\temp\INIT_620289" "11hw2ap_conet.f"


 link /INCREMENTAL:NO /NOLOGO /DLL /SUBSYSTEM:WINDOWS /MACHINE:X86 /ERRORREPORT:PROMPT @"C:\temp\INIT_620289\linkfilestod9p1.txt" /OUT:"C:\temp\INIT_620289\11hw2ap_dsusr.dll" /map:"C:\temp\INIT_620289\11hw2ap_dsusr.map"

 fort_cpp.lib(fort_code.obj) : error LNK2019: unresolved external symbol _CPPFUNCTION@12 referenced in function _TESTCPP
 C:\temp\INIT_620289\11hw2ap_dsusr.dll : fatal error LNK1120: 1 unresolved externals

 ERROR during link(1)... Aborted
conec/conet只是对外部库函数的Fortran调用:

      SUBROUTINE CONEC
C
      INCLUDE 'COMON4.INS'
C
      CALL TESTCPP         ( 55791,     0,     0,     0)
C
      RETURN
      END
      SUBROUTINE CONET
C
      INCLUDE 'COMON4.INS'
C
      IF (.NOT. IFLAG) GO TO 9000
C
C  NETWORK MONITORING MODELS
C
C
 9000 CONTINUE
C
      RETURN
      END

我见过几个不同的例子,从Fortran调用C++函数,但它们看起来稍微不同。在C++函数名称之前或之后,我注意到了<<代码> <代码>的不同用法。我如何知道使用哪一个:

\cppufunction
cppufunction
cppufunction
。我需要用C++来使用C++代码吗?我是否需要在Fortran代码中创建一个
别名:“\cppu function”

我正在使用以下编译器: ifort:IVF IA-32 v12.1.0.233 cl:v16.00.30319.01 x86


<> P>是否有什么东西可以将C++代码正确地链接到FORTRAN函数?

< P>问题是有很多选择。无、前后有一个或两个下划线、变量后或列表末尾的字符串长度、按值调用或按引用调用。大写、小写或原始命名。只有这些选项,正确的概率已经低于百分之一(1/3*1/3*1/2*1/2*1/3)

通过使用该实用程序内省.lib文件,并手动检查“英特尔fortran默认设置”和项目文件中的设置,可以稍微减少该值

正如一些人建议的那样,最优雅的方法是使用
bind(C)
和module的组合。
bind(C)
语句避免了知道名称mangling。
iso_c_绑定
提供和
integer(c_int)
而不是
integer*4
,以确保您的类型与c的兼容性。您必须知道fortran在默认情况下按引用调用,您可以使用
,value
按值调用。这会将你的成功率一直提高到1

这里是一个简单的例子,如何调用C++中定义的ADD1函数:

测试.f90

  program example

    use iso_c_binding
    implicit none

    interface
       integer(c_int) function add1(x) bind(C,name="add1")
         !DEC$ ATTRIBUTES DLLEXPORT :: add1
         use iso_c_binding
         integer(c_int), value :: x
       end function add1
    end interface

    call callingadd1()
  contains
    subroutine callingadd1()
      write(*,*) '1+1=', add1(1)
    end subroutine callingadd1
  end program example
subroutine callingadd1() bind(C, name="callingadd1")
  !DEC$ ATTRIBUTES DLLEXPORT :: callingadd1
  use iso_c_binding
  implicit none
  interface
     integer(c_int) function add1(x) bind(C,name="add1")
       !DEC$ ATTRIBUTES DLLEXPORT :: add1
       use iso_c_binding
       integer(c_int), value :: x
     end function add1
  end interface
  write(*,*) '1+1=', add1(1)
end subroutine callingadd1
add1.cpp

extern "C" {
  int add1(int x);
}

int add1(int x) {
  return(x+1);
}
仅使用子例程编辑示例。用于包含在共享对象/dll/dylib中

子程序.f90

  program example

    use iso_c_binding
    implicit none

    interface
       integer(c_int) function add1(x) bind(C,name="add1")
         !DEC$ ATTRIBUTES DLLEXPORT :: add1
         use iso_c_binding
         integer(c_int), value :: x
       end function add1
    end interface

    call callingadd1()
  contains
    subroutine callingadd1()
      write(*,*) '1+1=', add1(1)
    end subroutine callingadd1
  end program example
subroutine callingadd1() bind(C, name="callingadd1")
  !DEC$ ATTRIBUTES DLLEXPORT :: callingadd1
  use iso_c_binding
  implicit none
  interface
     integer(c_int) function add1(x) bind(C,name="add1")
       !DEC$ ATTRIBUTES DLLEXPORT :: add1
       use iso_c_binding
       integer(c_int), value :: x
     end function add1
  end interface
  write(*,*) '1+1=', add1(1)
end subroutine callingadd1

似乎您应该指定调用约定。cdecl或stdcall,我不知道,我只为Unix编程。最好的方法是使用Fortran 2003与C(和
iso_C_绑定模块
)的互操作性。我知道主程序是如何做到这一点的,但我很难将其与子例程一起使用。最近我用Fortran为一个Win32游戏做了一些dll,它“刚刚工作”很完美,当我使用Fortran 2003和iso_c_binding时,您的里程可能会有所不同。关于手动指定约定,我不能说任何事情。
iso_c_绑定
是否可以从
子例程
中完成,而不是像您建议的那样将其放入
程序
中?我更新了示例以使用子例程。您也可以将接口和子例程放在一个模块中,也可以将接口放在子例程中。这个网站上Fortran答案中常见的一个术语诡辩——内部模块ISO_C_绑定是C互操作性的一部分,但与OP的问题无关。这是他需要的BIND属性——如果你从你的例子中去掉USE语句,编译器仍然会得到正确的名称。使用“iso_c_binding”作为c互操作性的同义词是不准确的,可能会让新手感到困惑。我想我的问题是,是否可以单独在子例程模块中使用它。这将最终成为一个我无法控制的程序所使用的库。所以我想知道的是,是否需要在程序级定义
使用iso_c_绑定
隐式无
,或者是否可以在子例程中进行布局。请参阅额外示例。如果将其编译到dll中,该函数应该是可调用的。