2016-10-11 8 views
0

Dies ist ein bisschen eine komplizierte Frage zu erklären, und es beinhaltet technisch eine Menge Code, also werde ich mein Bestes tun, um es zu erklären. Wenn es sich herausstellt, dass ich Code schreiben muss, poste ich, wonach die Leute fragen, wenn sie danach fragen, um zu vermeiden, dass sie sich zu sehr auffüllen.Warum lädt mein C++ - Programm meine FORTRAN-Bibliothek nicht richtig?

Ich bin mir auch ziemlich sicher, ich weiß, was das allgemeine Problem ist, ich bin nur nicht sicher, wie es zu beheben oder herauszufinden, wie es zu beheben ist. Das meiste beschäftigt sich mit Dingen, über die ich sehr wenig weiß, und ich bin nur dort angekommen, wo ich bin, dank anderer SO-Fragen und zahlloser Google-Suchen und dergleichen, und viel Versuch und Irrtum, alles zusammen zu stopfen.

ich beginnen würde mit der Feststellung, dass ich glaube, das Problem ist, dass ein Teil von dem, was ich tue 32-Bit kompiliert wird, und ein Teil davon 64-Bit-. Hoffentlich ist das genau, und es wird Ihnen helfen, dies mit Ihrem Fokus an den richtigen Stellen zu lesen.

Grundsätzlich habe ich eine C++ - Code-Basis, die unter Windows mit CMake und Visual Studio 12 2013 erstellt und kompiliert wird, und eine FORTRAN-Codebasis, die unter Linux mit gfortran erstellt und kompiliert wird. Das Endziel besteht darin, das FORTRAN in eine Art Bibliothek zu verwandeln, die vom C++ - Code benutzt werden kann, und alles über CMake gut funktionieren zu lassen, so dass aktuelle Entwickler des C++ - Codes nichts extra oder ärger machen müssen um es zu benutzen.

Bisher habe ich eine kleine Beispielcode-Basis, mit der ich experimentiere, und sobald ich damit fertig bin, benutze ich dieselben Konzepte, um den eigentlichen Code zu erstellen.

Der Punkt, den ich bis zu bin, ist, dass es alles funktioniert gut, aber wenn ich das daraus resultierende Programm tatsächlich laufen, bekomme ich folgende Fehlermeldung:

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

Irgendwelche Ideen über das, was nicht in Ordnung ist (Google-Ergebnisse scheinen zu implizieren, dass die ausführbare Datei und die Bibliothek 32- und 64-Bit bzw. umgekehrt sind), und wie man es beheben kann?

Beachten Sie, dass dies alles unter Windows erstellt wird, es ist nur so, dass das FORTRAN mit gfortran im Makefile erstellt wird, das von CMake aufgerufen wird. Ich weiß eigentlich nicht genau, wie CMake make ruft. Ich habe MSYS2 installiert, und ich habe es damit arbeiten, bevor ich zu diesem Stadium komme, aber ich weiß nicht genau, wie CMake diesen Anruf macht. Wenn Sie wissen, wie ich das herausfinden könnte, lassen Sie es mich wissen!

Hier werde ich die schrecklich geschriebene CMakeLists.txt und Makefile posten, die ich verwende, um alles zu kompilieren. Wenn Sie andere Details sehen möchten, lassen Sie es mich wissen! Da es so viele bewegliche Teile gibt, bin ich mir nicht sicher, welche Dinge in Bezug auf Softwareversionen wirklich relevant sind. Bitte lassen Sie mich wissen, wenn Sie etwas wissen möchten.

Noch einmal, ich entschuldige mich für all meine Noobishness-- dieses Zeug ist nicht meine Stärke.

Makefile:(My Editor geändert Tabs zu Leerzeichen)

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

Es ist nicht ganz klar (vielleicht habe ich die Frage nicht gründlich genug gelesen) - Sie versuchen nicht, eine Windows-Programmdatei mit einer Linux-Bibliothek zu verknüpfen, oder? –

+0

Ich glaube nicht ... Sie werden beide auf Windows gebaut, nur das FORTRAN wird mit gfortran im Makefile erstellt, das von CMake aufgerufen wird. Ich weiß nicht, darüber nachzudenken, genau wie es 'make' nennt. Ich habe MSYS2 installiert, und ich habe es damit arbeiten, bevor ich zu diesem Zeitpunkt, aber ich weiß nicht, was CMake verwendet, um diesen Anruf zu machen. Wie würde ich herausfinden? –

+2

Nun, vielleicht möchten Sie Ihre Frage klären, es scheint, ich bin nicht die einzige Person, die zunächst verwirrt war. Wie für den Rest Ihres Kommentars, wenn Sie Material zu Ihrer Frage hinzufügen hinzufügen, stellen Sie keine zusätzlichen Fragen in Kommentaren, sie sind einfach zu schwer zu lesen. –

Antwort

0

Danke an alle Hilfe, aber vor allem @IanH hilft mir auf another related SO question, ich habe die ganze Sache endlich herausgefunden!

Die kurze Antwort ist, dass die DLL 64-Bit kompiliert wurde. Also habe ich gerade die 32-Bit-Version von MSYS2 mit allen entsprechenden Tools heruntergeladen und installiert (make, gcc, usw.), und jetzt funktioniert alles!

0

Sie versuchen, eine DLL-Bibliothek zu kombinieren erstellt gfortran unter Windows unter MSYS mit einem Visual Studio-Projekt mit C++.

Das Erstellen korrekter DLL-Dateien in Windows kann aus vielen Gründen schwierig sein, wie Aufrufkonventionen, Compiler-Flags und Sichtbarkeit der Funktionen. Alles in Ordnung zu bekommen, während man durch gfortran geht, ist wahrscheinlich technisch möglich, wird aber nicht empfohlen.

Es gibt zwei Hauptansätze.

1) Zuerst den Fortran-Code in C oder C++ übersetzen, dann entweder diesen Code direkt in Ihr C++ - Hauptprojekt integrieren (am einfachsten) oder mit normalen Methoden in eine DLL kompilieren (vorzugsweise mit Visual Studio) Werkzeugkette). Sie haben erwähnt, dass Sie Fortran 90 Code haben, also sollten Sie die Fable tool untersuchen.

2) Der zweite Ansatz besteht darin, eine DLL mit Ihrer MSYS gcc Toolchain mit C-Quellcode zu schreiben. Sobald Sie über eine funktionierende DLL verfügen, die aus Ihrem Visual Studio-Code aufgerufen werden kann, verknüpfen Sie Objektdateien, die mit gfortran kompiliert wurden. Die Idee besteht darin, das Problem in zwei Teile aufzuteilen, die unabhängig voneinander lösbar sind: eine DLL mit der gcc Toolchain erstellen und C- und Fortran-Code mischen. Wenn Sie Hunderte von Fortran-Funktionen haben, ist diese Methode möglicherweise nicht durchführbar, da Sie für jede Funktion einen Shim-Code schreiben müssen.

+5

Es ist nicht * so * schwierig. Viele Leute, die am Fortran-Tag teilnehmen, mischen routinemäßig Fortran und C oder C++. Eine Übersetzung wird normalerweise nicht benötigt. Ich habe selbst DLL verwendet kompiliert von gfortran als ein Plugin zu Windows-Spiel von MSVC++ kompiliert und die einzige notwendige Sache war, das Symbol mit dem richtigen Namen zu exportieren und rufen Sie die richtigen C-Symbole. –

+0

Sie haben wahrscheinlich Recht, meine Erfahrung in Windows ist veraltet. Ich erinnere mich nur daran, dass es Probleme gab, zuverlässig funktionierende Fortran-DLLs von MingGW zu bekommen. –

+1

Wenn Sie darauf bestehen, unterschiedliche Umgebungen wie MSVC++ und Gfortran zu mischen, scheint die Dll-Route am erfolgreichsten zu sein, aber das schien nicht das zu sein, was Sie ursprünglich vorhatten. Sie konnten den 32- und 64-Bit-Modus auf diese Weise nicht kombinieren, und Sie wären nicht von der Verantwortung für die Vereinbarung von Dekorationskonventionen befreit. – tim18

Verwandte Themen