这是一个需要解释的复杂问题,技术上涉及很多代码,所以我会尽力解释它。如果事实证明我需要发布代码,我会发布人们要求的部分,因为他们要求它,以避免混淆太多。
我也很确定我知道一般问题是什么,我只是不确定如何解决它或弄清楚如何解决它。其中大部分内容涉及我所知甚少的内容,而且我只是因为其他SO问题和无数谷歌搜索之类的东西而得到了我所处的位置,以及大量拼凑错误的试验和错误。
我首先要说的是我认为问题在于我正在做的部分是32位编译,而部分是64位。希望这是准确的,它将帮助您在适当的地方重点阅读本文。
基本上我有一个C ++代码库,它是在Windows上使用CMake和Visual Studio 12 2013构建和编译的,以及一个FORTRAN代码库,它是在Linux上使用gfortran构建和编译的。最终目标是使FORTRAN成为某种可供C ++代码使用的库,并通过CMake使其完美地运行,使得C ++代码的当前开发人员无需执行任何额外操作或烦人的操作使用它。
到目前为止,我已经有一个我正在尝试的小示例代码库,一旦我使用它,我将使用相同的概念来使实际代码工作。
我要说的是它一切正常,但是当我实际运行生成的程序时,我收到以下错误:
The application was unable to start correctly (0xc000007b). Click OK to close the application.
关于出错的任何想法(Google结果似乎暗示可执行文件和库分别为32位和64位,反之亦然),以及如何修复它?
请注意,这一切都是在Windows上构建的,只是在Makefile中使用gfortran构建FORTRAN,这是从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
答案 0 :(得分:0)
您正尝试将使用MSYS下的Windows上的gfortran
创建的DLL库与使用C ++的Visual Studio项目相结合。
在Windows中创建正确的DLL文件可能很棘手,原因很多,例如调用约定,编译器标志和函数可见性。在完成gfortran
的过程中确保一切正确可能在技术上是可行的,但不建议这样做。
主要有两种方法。
1)首先将Fortran代码转换为C或C ++,然后将代码直接集成到主C ++项目中(最简单)或使用常规方法将其编译成DLL(最好使用Visual Studio保留单个工具链) )。您提到您拥有Fortran 90代码,因此您应该调查Fable tool。
2)第二种方法是使用MSYS gcc
工具链使用C源代码编写DLL。一旦有了可从Visual Studio代码调用的工作DLL,就可以链接使用gfortran
编译的目标文件。我们的想法是将问题分成两部分,这两部分是可以独立解决的:使用gcc
工具链制作DLL,混合使用C和Fortran代码。如果您有数百个Fortran函数,则此方法可能不可行,因为您需要为每个函数编写一些填充码。
答案 1 :(得分:0)
感谢大家的帮助,尤其是@IanH帮我another related SO question,我终于弄明白了!
简短的回答是DLL正在64位编译。所以我刚下载并使用所有适当的工具(make
,gcc
等)安装了32位版本的MSYS2,现在一切正常!