为什么我的C++程序无法正确加载我的 FORTRAN 库?
Why won't my C++ program properly load my FORTRAN library?
要解释这个问题有点复杂,从技术上讲,它涉及大量代码,所以我将尽力解释它。如果事实证明我需要张贴代码,我会张贴人们要求的部分,因为他们要求它,以避免把它弄得太乱。
我也相当确定我知道一般的问题是什么,我只是不确定如何解决它或找出如何解决它。其中大部分都是我所知甚少的东西,多亏了其他SO问题和无数的谷歌搜索之类的,以及大量的试验和错误,我才有了今天的成就。
我将首先声明我认为问题是我正在做的部分被编译为32位,部分被编译为64位。希望这是准确的,它会帮助你在阅读这篇文章时把注意力集中在正确的地方。
基本上,我有一个c++代码库,它是用CMake和Visual Studio 12 2013在Windows上构建和编译的,还有一个FORTRAN代码库,它是用gfortran在Linux上构建和编译的。最终目标是使FORTRAN成为某种可以被c++代码使用的库,并使其通过CMake很好地工作,以便当前的c++代码开发人员不必为了使用它而做任何额外的或烦人的事情。
到目前为止,我已经有了一个小的示例代码库,我正在进行试验,一旦我让它工作,我将使用相同的概念使实际的代码工作。 我想说的是,这一切都工作得很好,但是当我实际运行结果程序时,我得到以下错误: The application was unable to start correctly (0xc000007b). Click OK to close the application.
有什么想法是错误的(谷歌的结果似乎暗示可执行文件和库分别是32位和64位,或者相反),以及如何修复它?
请注意,这都是在Windows上构建的,只是FORTRAN是用gfortran在Makefile中构建的,它是从CMake中调用的。我不知道CMake是怎么调用make
的。我确实安装了MSYS2,在到达这个阶段之前,我得到了它的工作,但我不知道CMake是如何进行该调用的。如果你知道我怎样才能找到答案,请告诉我!
在这里,我将发布可怕的写CMakeLists.txt和Makefile我用来编译一切。如果你想了解其他具体情况,请告诉我!此外,由于有这么多的活动部分,我不确定在软件版本方面,哪些东西是真正相关的。如果你想知道什么,请告诉我。
再次为我的无礼道歉——这不是我的强项。
Makefile:(我的编辑器将制表符更改为空格)
FC=gfortran -g
CC=g++ -g
DLL_SRC_DIR=.
BUILD_DIR=build
all:
$(FC) -c $(DLL_SRC_DIR)/fdll.f90 -o $(BUILD_DIR)/fdll.o
$(CC) -c -DBUILDING_C_DLL $(DLL_SRC_DIR)/cdll.cpp -o $(BUILD_DIR)/cdll.o
$(CC) -shared -o $(BUILD_DIR)/libcdll.dll $(BUILD_DIR)/cdll.o $(BUILD_DIR)/fdll.o -Wl,--out-implib,$(BUILD_DIR)/libcdll.a,--output-def,$(BUILD_DIR)/libcdll.def -lgfortran
/c/Program Files (x86)/Microsoft Visual Studio 12.0/VC/BIN/lib /MACHINE:x86 /DEF:$(BUILD_DIR)\libcdll.def /OUT:$(BUILD_DIR)\libcdll.lib
clean:
rm -f $(BUILD_DIR)/*
CMakeLists.txt
project(cmake_test)
add_executable(cprog cprog.cpp)
find_path(FORTRAN_DIR NAMES cdll.cpp fdll.f90 Makefile PATHS ../source)
execute_process(COMMAND make
WORKING_DIRECTORY ${FORTRAN_DIR})
set(FORTRAN_LIB ${FORTRAN_DIR}/build/libcdll.lib)
include_directories(${FORTRAN_DIR})
set(MY_LIBRARIES ${MY_LIBRARIES} ${FORTRAN_LIB})
target_link_libraries(cprog ${MY_LIBRARIES})
# See: http://stackoverflow.com/questions/10671916/how-to-copy-dll-files-into-the-same-folder-as-the-executable-using-cmake
add_custom_command(TARGET cprog POST_BUILD # Adds a post-build event to cprog
COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake -E copy_if_different..."
"${FORTRAN_DIR}/build/libcdll.dll" # <--this is the file to copy
$<TARGET_FILE_DIR:cprog>) # <--this is where to copy it
您正在尝试将使用gfortran
在Windows下在MSYS下创建的DLL库与使用c++的Visual Studio项目相结合。
在Windows中创建正确的DLL文件可能会有很多棘手的原因,比如调用约定、编译器标志和函数可见性。在完成gfortran
的过程中,让一切都正确在技术上是可能的,但不推荐。
有两种主要的方法。
1)首先是将Fortran代码翻译成C或c++,然后将该代码直接集成到您的主要c++项目中(最简单),或者使用常规方法将其编译成DLL(最好使用Visual Studio保持单个工具链)。您提到您有Fortran 90代码,因此您应该研究一下Fable工具。
2)第二种方法是使用C源代码使用MSYS gcc
工具链编写DLL。一旦你有了一个可以从你的Visual Studio代码中调用的工作DLL,链接使用gfortran
编译的目标文件。我们的想法是将问题分成两个独立解决的部分:使用gcc
工具链制作DLL,以及混合C和Fortran代码。如果您有数百个Fortran函数,则此方法可能不可行,因为您需要为每个函数编写一些shim代码。
感谢大家的帮助,特别是@IanH在另一个相关的SO问题上帮助我,我终于弄清楚了整个事情!
简短的回答是DLL被编译为64位。所以我只是下载并安装了32位版本的MSYS2和所有适当的工具(make
, gcc
等),现在一切都工作了!
- 当我尝试加载内核模块时,如何修复C++中的这个 malloc() 错误?
- 0xc000007b Windows 上的 OpenCL 库的加载时间错误
- 我可以加载与库静态链接的 dll 吗?
- jvm.dll 上的加载库失败,错误代码为 183
- 我如何加载多个脚本而没有变量问题
- 如何调试 Excel 对 COM 服务器的加载?
- 为什么我在加载共享库时遇到错误
- gcc矢量扩展中未对齐的加载/存储
- Qt 如何获取发送者信号的发送者或如何知道 QWebEngineView 的加载启动网址
- OPENCV_使用OpenCV2的加载图像中的异常
- 我无法加载数据文件,总是无法打开它
- Boost:在单独的加载/保存函数中非侵入性地序列化类
- 附加相同的加载项,但在 Excel 启动时来自不同的文件夹
- Marlett Font:我可以加载它并在WinAPI中使用它吗?
- IE插件中的加载库不起作用
- 赋值是否等同于 std::atomic <bool>的加载/存储
- C++ Boost::序列化"no matching function for call"到我的加载函数参数中类的构造函数
- 如何防止编译器优化对从未使用的变量的加载
- C++Boost.序列化与简单的加载/保存
- 我的加载图像不起作用 - 我需要知道为什么