为什么我的C ++程序不能正确加载我的FORTRAN库?

时间:2016-10-11 16:42:54

标签: c++ visual-studio dll cmake fortran

这是一个需要解释的复杂问题,技术上涉及很多代码,所以我会尽力解释它。如果事实证明我需要发布代码,我会发布人们要求的部分,因为他们要求它,以避免混淆太多。

我也很确定我知道一般问题是什么,我只是不确定如何解决它或弄清楚如何解决它。其中大部分内容涉及我所知甚少的内容,而且我只是因为其他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

2 个答案:

答案 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位编译。所以我刚下载并使用所有适当的工具(makegcc等)安装了32位版本的MSYS2,现在一切正常!