关于Fortran调用C++函数的小结

关于Fortran调用C++函数的小结
2017-3-12
背景
工作中遇到了需要在Fortran代码中调用C++提供的函数的情况。
通过在网上查阅资料,总结了实现方法,制作了一个实例。
工具
集成开发环境是VS2010。由于默认安装模式下的VS2010是无法编译调试Fortran的,所以又补充安装了Intel(R) Virual Fortran 2011(英特尔可视化Fortran编译器)。
参考资料分析
本文需要用到Fortran与C/C++的混合编程,Fortran和C/C++分别编译各自的功能模块源代码,得到各自的目标文件(.obj),然后集成链接这些obj 文件生成一个统一的可执行文件,实现对对方函数的调用,数据交换通过约定接口来实现[1]
C++代码中函数说明前需要用到extern关键字,说明函数可以在本模块或其它模块中使用[2]流量生成。extern与"C"一起连用时,如: extern "C" void fun(int a, int b);则告诉编译器在编译fun这个函数名时按着C的规则去翻译相应的函数名而不是C++的,C++的规则在翻译这个函数名时会把fun这个名字变得面目全非[3]
要在Fortran中调用C++的函数,意味着Fortran项目对C++项目产生了依赖关系,如果项目依赖项未设置会导致类似“无法解析的外部符号 _XXX,该符号在函数 _XX 中被引用”的错误。另外还要保证Fortran与C++项目的运行库设置都是“多线程调试”[4]
实现过程
创建Fortran项目
1)启动VS2010,新建一个Fortran控制台应用程序,名称为Console1。
2)在该项目下的Source Files下添加一个新文件Source1.f90。
3)在Source1.f90中写入如下代码:
program main
    implicit none
    interface
        上海建通subroutine SUB(a,b)
            !DEC$ ATTRIBUTES C,ALIAS:'_sub'::SUB
            !DEC$ ATTRIBUTES reference::a,b
            integer a , b
        end subroutine SUB
    end interface
    integer(4) a,b,c
    a=100
    b=1
    write(*,*) "开始调用C++里的函数SUB"
    call SUB(a,b)
    read(*,*)
end program main
注:接口中为_sub这个来自于C++的函数起了个别名SUB,所以在后面调用SUB时其实就是调用_sub。在接口中还规定了a和b两个参数的传递方式是传引用。
创建C++项目
在解决方案资源管理器中的“解决方案”处右键,添加一个新建项目,在新建窗口中选中Win32控制台应用程序,输入项目名称Cpp2。在随后弹出的应用程序设置中选择应用程序类型为静态库。
在项目的头文件中新建一个sub.h,在其中输入如下代码:
晋中阳光农廉网
//sub.h
#ifndef _SUB_H
    #define _SUB_H
    extern "C" void _cdecl sub(int *a,int *b);
#endif
注:在头文件中使用#ifdef和#ifndef是非常重要的,可以防止双重定义的错误[5]山西财政厅
在项目的源文件中新建一个sub.cpp,在其中输入如下代码:
//sub.cpp
#include "stdafx.h"
#include "sub.h"
#include <iostream>
extern "C" void _cdecl sub(int *a,int *b)
{
    std::cout<<"C++: 已经进入C++的函数内部\n"<<素娥篇"a="<<*a<<", b="<<*b<<std::endl;
    std::cout<<"a - b = "<<(*a - *b)<<std::endl;
}
注:extern表示这个函数可以被外部使用;"C" 表示使用C的方式编译、生成,这样生成的函数名就会是_sub,而不是按C++默认的方式变成_sub@数字;_cdecl表示编译生成的obj文件中函数名为混合大小写格式,本例中的sub本来就全是小写,所以会变成_sub;另外注意:这里参数是指针,取值要用*a和*b。
设置Fortran项目的项目依赖项
在Console1项目上右键,选择项目依赖项,在弹出窗口中依赖项页内选中Cpp2,切换到生成顺序页,可以看到Cpp2排在Console1前面。
设置运行库
1)设置Fortran项目的运行库,在Console1项目上右键选择属性,然后到【配置属性】【Fortran】【Libraries】【Runtime Library】,设置其值为Debug Multithreaded(/libs:static/threads/dbglibs)即多线程调试。
2)设置C++项目的运行库,在Cpp2项目上右键选择属性,到【配置属性】【C/C++】【代码生成】【运行库】,设置其值为多线程调试(/MTd)。
生成项目
1)在解决方案上右键选择重新生成解决方案。
2)在解决方案所在的Console1文件夹下到Debug文件夹,可以看到其中有一个Cpp2.lib文件,这个静态库文件就是Cpp2项目生成的。
3)在Console1\Console1\Debug文件夹下可以看到文件,这个可执行文件是Console1项目生成的。
注:如果要单独生成Cpp2,可以在Cpp2项目上右键选择重新生成。如果在Console1项目上右键选择重新生成,因为前文设置了项目依赖项的关系,Cpp2也会被生成。
启动调试
按下F5,启动调试。可以看到调试成功。
参考文献
[1] suiyi1234546,第11章 Fortran和C的混合语言编程-授课版,百度文库,wenku.baidu/link?url=ogwgYldzkmbgJXM86iXjAMt60wimIN1bMVy6uoz1dFn0pWuPPj1mKapYZ9RAK1rXrMZCmQAmJYjGCA0B1IpvDh9wb1joBcFdJ3VO2fz19jO
[2] ForFreeDom,关于C++的extern关键字 ,博客园,
[3]  chao_yu,C/C++中extern关键字详解,博客园,wwwblogs/yc_sunniwell/archive/2010/07/14/1777431.html
[4] zihahage,VS2010 环境下链接 IVF2011 编译的 Fortran 静态库问题,新浪博客,blog.sina/s/blog_6798850f0101daea.html
[5] Arthursky,C++在头文件中使用#ifdef和#ifndef ,ChinaUnix,blog.chinaunix/uid-11572501-id-2868707.html常压渣油

本文发布于:2024-09-21 18:34:35,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/444442.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:函数   项目   生成   选择   设置   文件
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议