B. Eckles B. Eckles - 1 month ago 8
C++ Question

Why won't my C++ program properly load my FORTRAN library?

This is a bit of a complicated question to explain, and it technically involves a lot of code, so I'm going to do my best to explain it. If it turns out I need to post code, I'll post what parts people ask for, as they ask for it, so as to avoid cluttering this up too much.

I'm also fairly sure I know what the general problem is, I'm just not sure how to fix it or figure out how to fix it. Most of this deals with stuff I know very little about, and I've only gotten to where I am thanks to other SO questions and countless Google searches and the like, and lots of trial and error of cobbling it all together.

I'll start off by stating that I believe the problem is that part of what I'm doing is being compiled 32-bit, and part of it 64-bit. Hopefully that's accurate, and it'll help you to read this with your focus in the right places.

Basically I've got a C++ code base which is built and compiled on Windows with CMake and Visual Studio 12 2013, and a FORTRAN code base which is built and compiled on Linux with gfortran. The end goal is to make the FORTRAN into some sort of library which can be used by the C++ code, and have it all work nicely via CMake such that current developers of the C++ code don't have to do anything extra or annoying in order to use it.

So far, I've got a small example code base which I'm experimenting with, and once I get it to work with that, I'll use the same concepts to make the actual code work.

The point I'm up to is that it all works nicely, but when I actually run the resulting program, I get the following error:

The application was unable to start correctly (0xc000007b). Click OK to close the application.


Any ideas about what is going wrong (Google results seem to imply that the executable and the library are 32- and 64-bit, respectively, or vis versa), and how to fix it?

Note that this is all being built on Windows, it's just that the FORTRAN is being built with gfortran in the Makefile, which is being called from CMake. I don't actually know exactly how CMake is calling
make
. I do have MSYS2 installed, and I got it working with that before getting to this stage, but I don't know exactly how CMake is making that call. If you know how I could find that out, please let me know!

Here I will post the horribly written CMakeLists.txt and Makefile I'm using to compile everything. If you would like to see other specifics, please let me know! Also, since there are so many moving parts, I'm not sure which things it's really relevant to mention in terms of versions of software. Please let me know if there's anything you'd like to know.

Again, I apologize for all of my noobishness-- this stuff is not my forte.

Makefile: (My editor changed tabs to spaces)

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

Answer

Thanks to everyone's help, but especially to @IanH helping me on another related SO question, I've got the whole thing figured out finally!

The short answer is that the DLL was being compiled 64-bit. So I just downloaded and installed the 32-bit version of MSYS2 with all of the appropriate tools (make, gcc, etc), and now everything works!