Windows下C++/Fortran调用.exe可执行文件
软件环境
# 操作系统 = Windows10
# 编译链工具 =
#	gcc, g++, GNU Fortran (MinGW.org GCC Build-2) 9.2.0
#	GNU Make 3.82.90	Built for i686-pc-mingw32
#	GNU ld (GNU Binutils) 2.32
#	CMake version 3.18.1
本机安装了MinGW编译工具,并将<安装路径>\MinGW\bin添加到环境变量中。
Windows下CMake编译配置
设置项目的generator
在本机使用CMake过程中发现,默认使用NMake Makefiles作为generator,因为没有安装因此配置失败。
希望设置generator为已安装的MinGW Makefiles。
Command Line
cmake .. -G "MinGW Makefiles"
CMake GUI
初次Configure时指定项目的generator。
选用MinGW Makefiles,使用默认编译器。
如果已经指定generator后,需要修改。可以清除CMake Cache后再次Configure,File->Delete Cache。
PreLoad.cmake
CMake设置generator是在处理CMakeLists.txt之前的,因此不能通过在CMakeLists.txt中设置CMAKE_GENERATOR达到修改默认generator的作用。
可以在项目根目录添加PreLoad.cmake这样的文件实现预先修改配置,内容如下。
set(CMAKE_GENERATOR "MinGW Makefiles" CACHE INTERNAL "" FORCE)
设置make
即使已为MinGW添加了环境变量,但是不能在命令行中直接使用make。gcc、g++、gfortran可以直接使用。
是因为在<安装路径>\MinGW\bin下,对应make的可执行程序名字为mingw32-make,在同目录下拷贝一份,重命名为make即可使用。
示例程序
CMake
以下为CMakeLists.txt文件内容,
# name: exe_test
# date: 2021/3/14
#
cmake_minimum_required(VERSION 3.3)
project(exe_test CXX Fortran)
add_executable(hello source/hello.cpp)
add_executable(caller_cpp source/caller.cpp)
add_executable(caller_fort source/caller.f90)
设置Fortran语言的一个小问题
-->$ cmake ..
-- The CXX compiler identification is GNU 9.3.0
CMake Error: Could not find cmake module file: CMakeDetermineFORTRANCompiler.cmake
CMake Error: Error required internal CMake variable not set, cmake may not be built correctly.
Missing variable is:
CMAKE_FORTRAN_COMPILER_ENV_VAR
CMake Error: Error required internal CMake variable not set, cmake may not be built correctly.
Missing variable is:
CMAKE_FORTRAN_COMPILER
...
这个问题的原因在CMakeLists.txt中,是大小写敏感的,Fortran只应该使用首字母大写的形式。
# project(exe_test CXX FORTRAN)
project(exe_test CXX Fortran)
source/hello.cpp
// name: hello.cpp
// date: 2021/3/14
//
#include <iostream>
using namespace std;
int main()
{
        cout << "Aloha!" << endl;
        return 0;
}
source/caller.cpp
// name: caller.cpp
// date: 2021/3/14
//
#include <iostream>
#include <string>
#include <Windows.h>
#include <tlhelp32.h>
#include <process.h>
using namespace std;
void Launch(LPCTSTR lpApplicationName)
{
        // additional information
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
        // set the size of the structures
        ZeroMemory( &si, sizeof(si) );
        si.cb = sizeof(si);
        ZeroMemory( &pi, sizeof(pi) );
        // start the program up
        CreateProcess( lpApplicationName,   // the path
                        (char*)"",        // Command line
                        NULL,           // Process handle not inheritable
                        NULL,           // Thread handle not inheritable
                        FALSE,          // Set handle inheritance to FALSE
                        0,              // No creation flags
                        NULL,           // Use parent's environment block
                        NULL,           // Use parent's starting directory
                        &si,            // Pointer to STARTUPINFO structure
                        &pi             // Pointer to PROCESS_INFORMATION structure (removed extra parentheses)
        );
        cout << "process id: " << pi.dwProcessId << ", thread id: " << pi.dwThreadId << endl;
        // Close process and thread handles.
        CloseHandle( pi.hProcess );
        CloseHandle( pi.hThread );
}
int main(int argv, char* args[])
{
        cout << "caller_cpp:" << endl;
        // 1.
        // 可以加路径,路径中应使用\\而非/
//      WinExec("hello.exe", SW_SHOW);
        // 2.
//      SHELLEXECUTEINFO shell = { sizeof(shell) };
//      shell.fMask = SEE_MASK_FLAG_DDEWAIT;
//      shell.lpVerb = "open";
//      shell.lpFile = "hello.exe";
//      shell.nShow = SW_SHOWNORMAL;
//      BOOL ret = ShellExecuteEx(&shell);
    	// 3.
        // ShellExecuteA
//      ShellExecute(NULL, "open", "hello.exe", NULL, NULL, SW_SHOWDEFAULT);
        // 4.
//      system("hello.exe");
        // 5.
        Launch("hello.exe");
        // 6.
//      _execv("hello.exe", args);
        return 0;
}
收集了多种方式,建议使用CreateProcess(),详细内容查阅Microsoft Docs。
source/caller.f90
! name: caller.f90
! date: 2021/3/14
!
PROGRAM Caller_fort
        PRINT *, "Caller_fort"
        ! Fortran 2008
        call execute_command_line ("hello.exe", wait=.false.)
        !
        call system("hello.exe")
END
execute_command_line是Fortran2008标准开始支持的函数。
参考资料
- cmake_ Selecting a generator within CMakeLists.txt - Stack Overflow
- Using cmake with fortran - Stack Overflow
- windows C_C++ 在一个程序中打开,关闭和监视其它的exe程序_lumanman_的博客-CSDN博客
- C++ 打开exe文件的方法(VS2008) - work hard work smart - 博客园
- C++ 中打开 exe 文件_楠木大哥的博客-CSDN博客
- C++程序中调用exe可执行文件_积累点滴,保持自我-CSDN博客_c++调用exe文件
- ShellExecuteA function (shellapi.h) - Win32 apps _ Microsoft Docs
- Creating Processes - Win32 apps _ Microsoft Docs
- _exec, _wexec Functions _ Microsoft Docs
- EXECUTE_COMMAND_LINE (The GNU Fortran Compiler)
- SYSTEM (The GNU Fortran Compiler)
Windows下C++/Fortran调用.exe可执行文件的更多相关文章
- windows下使用批处理调用exe和服务
		手动调用exe或者启动服务很麻烦,可以使用.bat批处理文件,双击运行即可.步骤如下:创建一个新的txt文件但是保存成.bat结尾的文件(选择用记事本打开编写命令),输入代码内容格式如下: @echo ... 
- Windows下打包Python的exe可执行文件
		参考:http://www.cnblogs.com/Lands-ljk/p/5447723.html 
- Linux的.a、.so和.o文件 windows下obj,lib,dll,exe的关系
		Linux的.a..so和.o文件 - chlele0105的专栏 - CSDN博客 https://blog.csdn.net/chlele0105/article/details/23691147 ... 
- Linux的.a、.so和.o文件 windows下obj,lib,dll,exe的关系 动态库内存管理   动态链接库搜索顺序   符号解析和绑定 strlen函数的汇编实现分析
		Linux的.a..so和.o文件 - chlele0105的专栏 - CSDN博客 https://blog.csdn.net/chlele0105/article/details/23691147 ... 
- C/C++ ShellExecuteEx调用exe可执行文件
		本系列文章由 @YhL_Leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/49591995 以商业的软件Enblen ... 
- 关于windows下c++生成的exe发布时的依赖dll问题
		如同linux下通常要求安装特定版本的libstdc++一样,windows下vc++生成的exe发布时的依赖dll问题,可以参见帖子,http://bbs.csdn.net/topics/39105 ... 
- Windows下C语言调用dll动态链接库
		dll是windows下的动态链接库文件,下面记录一下在windows下如何调用C语言开发的dll动态链接库. 1.dll动态链接库的源代码 hello_dll.c #include "st ... 
- golang 在 windows 下编译出 linux 二进制可执行文件的软件套装合集 [go 1.7.3环境]
		golang 很好用,不过要把工具链弄完整. 要不你会发现怎么不能编译跨平台的呀? 怎么写代码没提示啊? ... 这一整套弄下来并不容易. 所以精心准备了一套工具方便大家使用. 软件列表如图. 安装顺 ... 
- windows下使用c++调用redis
		不废话,unix下c++调用 redis可以看这个: http://blog.csdn.net/youngqj/article/details/8266177 ==================== ... 
随机推荐
- MacBook Pro 2019 13 inch & screen blink
			MacBook Pro 2019 13 inch & screen blink MacBook Pro 闪屏 https://macreports.com/mac-how-to-trouble ... 
- 「NGK每日快讯」12.11日NGK公链第38期官方快讯!
- 2021-2-20:请你说说分布式系统 BASE 理论是什么?
			BASE 理论是由 Dan Pritchett 在 ACM 上发表的一篇论文中提出的理论.是在 CAP 理论基础上提出的一种更实际的理论指导,和 PACELC 理论是有些相近的地方的. BASE 是指 ... 
- 使用RSEM进行转录组测序的差异表达分析
			仍然是两年前的笔记 1. prepare-reference 如果用RSEM对比对后的bam进行转录本定量,则在比对过程中要确保比对用到的索引是由rsem-prepare-reference产生的. ... 
- Java中出现Unhandled exception的原因
			说明某个方法在方法声明上已经声明了会抛异常,那么在调用这个方法的时候,就必须做异常处理,处理的方式有2种,要么try-catch这个异常,要么继续往上一层抛出这个异常,这是java语法要求的,必须这么 ... 
- 解决bs4在python中出现“ImportError: cannot import name ‘HTMLParseError‘”错误
			在使用BeautifulSoup4时候出现了ImportError: cannot import name 'HTMLParseError'的错误. 根本原因是BeautifulSoup在4.4.0以 ... 
- Flannel和Calico网络插件工作流程对比
			Flannel和Calico网络插件对比 Calico简介 Calico是一个纯三层的网络插件,calico的bgp模式类似于flannel的host-gw Calico方便集成 OpenStac ... 
- 求幂&&快速幂&&位运算
			1.普通的求幂方法: 时间复杂度为O(n),对于比较大的数在1s限时内可能会TLE int pow(int base,int p){ int ans=1; for(int i=1;i<=p;i+ ... 
- python进阶(12)闭包
			闭包 首先了解一下:如果在一个函数的内部定义了另一个函数,外部的我们叫他外函数,内部的我们叫他内函数. 在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用 ... 
- Azure Synapse Analytics Serverless
			数据湖仓 自从Databricks提出Lakehouse后,同时Snowflake的上市,湖仓一体成为数据领域最火热的话题. https://databricks.com/blog/2020/01/3 ... 
