Can not bind GDNative compiled with CMakeLists in 3.3 and 3.x via Mingw-w64 (Windows)
Repo branch: 3.3 (and a few others)
Godot version: 3.3.stable
After lots of trial and errors, comparing multiple guides, docs, tutorials, different versions, different toolchains and different C++ standards I managed to make godot-cpp compile and generate the required files & bindings on Windows with the 3.3 (and some others) branches by using the included CMakeLists.txt instead of SCons, and the linked commits of godot-headers; the GDNative project also compiles successfully, and generates a .dll. However, no matter what I try, trying to bind the dll in Godot results in the extremely obnoxious Windows "Error 126" which doesn't give back any kind of hint as to why.
This is the error as appears in one of my projects, https://github.com/Banderi/EMWaves/tree/master/CLionCPP and compiled on CLion with Mingw-w64 9.0/GCC 11.2.0 on C++14:
ERROR: Can't open dynamic library: E:/Godot/Projects/EMWaves/Godot/gdnative_cpp/windows/libwavescpp.dll, error: Error 126: The specified module could not be found.
.
At: platform/windows/os_windows.cpp:2425
ERROR: get_symbol: No valid library handle, can't get symbol from GDNative object
At: modules/gdnative/gdnative.cpp:502
ERROR: init_library: No nativescript_init in "res://gdnative_cpp/windows/libwavescpp.dll" found
At: modules/gdnative/nativescript/nativescript.cpp:1479
This error is extremely deceiving and frustrating because it's a generic error message that Windows throws when the .dll fails to load, NOT (necessarily) because the file is not found; it appears many many times over various threads on Discord, Reddit, Github, the forums etc. and it's incredibly rare to find a solution for it because it can happen for a multitude of different reasons. (e,g, https://github.com/godotengine/godot-cpp/issues/540 https://github.com/godotengine/godot-cpp/issues/403 https://github.com/godotengine/godot-cpp/issues/232 https://github.com/godotengine/godot-cpp/issues/14)
Here's what I made 100% sure of, in my project's case:
- The files and folder structures are correct All the files, the folders, the paths and file permissions have been quadruple checked and there's no issues with spaces, capitals, slashes etc. anywhere that I can see; the C99 GDNative ones in my repo also work fine.
- The .gdns and .gdnlib files are all set up correctly I've taken the files as have been presented from the sample files and just changed the details inside. I've also tried making new ones from inside Godot, to the same results; the C99 GDNative ones work correctly.
- The Godot project's code (gdscript) for setting up GDNative is correct
I've used the same code as the sample files, as well as my own from https://github.com/Banderi/GDNativeExample to the same effect. The C99 GDNative version works correctly, but the others do not. The error is the exact same that appears all the time as I mentioned in that repo's Readme, which is gdscript failing on the
<library res here>.new()line withAttempt to call function 'new' in base 'NativeScript' on a null instance.error -- this is the gdscript equivalent of the abovementionedError 126: The specified module could not be found.message; it appears when the .dll fails to load, under any circumstance, without a way to get any more clues about it. - There is no issue with the binds naming, the Class Name or the symbol prefix
The
nativescript_initerror above is another huge misdirect, as the issue has nothing to do with the init function being not found, invalid, etc. To confirm this, here's the actual error that appears when the init function export is missing, incorrect, or the symbol lookup fails (e.g. if the symbol prefix is incorrect):RROR: Can't resolve symbol godot_gdnative_init, error: 127. At: platform/windows/os_windows.cpp:2445 RROR: initialize: Failed to obtain godot_gdnative_init symbol At: modules/gdnative/gdnative.cpp:361 RROR: get_symbol: No valid library handle, can't get symbol from GDNative object At: modules/gdnative/gdnative.cpp:502 RROR: init_library: No nativescript_init in "res://gdnative_cpp/windows/libwavescpp.dll" found At: modules/gdnative/nativescript/nativescript.cpp:1479 - The GDNative code is correct
I've used the exact same code of the sample files, as well my own to see if something went wrong or the example code was outdated, to no avail.
Some other misc/useful information from testing things:
- The Godot app stops when reaching the error if ran from the Godot editor, but if ran from inside the C++ IDE (CLion) it just continues as normal so long as the GDNative library isn't further used in scripts.
- 3.x fails only when the API calls inside the init exports such as
Godot::gdnative_init(o);orGodot::gdnative_terminate(o);are present, while 3.3 branch fails as soon as either#include <Godot.hpp>or#include <Reference.hpp>are present. Even if thegodot-cppgenerated libs (libgodot-cpp.windows.release.64.a) aren't linked inside the 3.3 .dll, it will fail. - In 3.x, if the init exports are correct but empty (no API calls in the code) the library will bind correctly without the
Error 126, but gdscript will still throw theAttempt to call function 'new' in base 'NativeScript' on a null instance.and fail as normal. - Compiling in debug or release mode, as well as compiling the bindings with or without the
-gflag underGODOT_COMPILE_FLAGSdoesn't have any effect. - Mingw-w64 6.00/GCC 8.1.0 fails to compile either
godot-cppor the GDNative project. - I've heard some people say using the MSVC toolchain fixed similar issues, unfortunately I do not have Visual Studio and couldn't make the VSBuildTools work with CLion... yet.
- Using different C++ standards (e.g. C++17 or C++20) made no difference.
- The example from https://github.com/BastiaanOlij/gdnative_cpp_example also fails in the same manner as 3.x.
- The 3.3-stable branch from May (https://github.com/godotengine/godot-cpp/tree/godot-3.3-stable) behaves exactly as 3.3, however it initially fails to compile in CMake due to forward slashes. I temporarily fixed it on my end by using:
et(SOURCES_FILE_LIST_GOOD ) et(HEADERS_FILE_LIST_GOOD ) file(TO_CMAKE_PATH "${SOURCES_FILE_LIST}" SOURCES_FILE_LIST_GOOD) file(TO_CMAKE_PATH "${HEADERS_FILE_LIST}" HEADERS_FILE_LIST_GOOD) # Define our godot-cpp library add_library(${PROJECT_NAME} ${SOURCES} ${SOURCES_FILE_LIST_GOOD} ${HEADERS} ${HEADERS_FILE_LIST_GOOD} )
As I notice 3.x is the closest to being working, I suppose that's the one I should focus on if there's anything else to try. Here's my full project with all the files: https://github.com/Banderi/EMWaves It contains both the C++ attempts (CLionCPP) and a plain C one (CLion) which loads and works as intended.
Just to be safe, here's the steps I took to build the repos & libraries:
- Download
godot-cppof the branch selected in the dropdown menu as well as the linkedgodot-headers - Put the
godot-headersfiles inside the predisposed "godot-headers" folder in the root - Removed the
-gflag fromGODOT_COMPILE_FLAGSto reduce the library size - Generated the C++ bindings and compiled the
godot-cpprepo successfully with Mingw-w64 9.0/GCC 11.2.0 - Created a new C++ GDNative project in CLion, added the following folders to the inclusions:
<godot-cpp repo>/include/core--><gdnative project>/include/core<godot-cpp repo>/cmake-build-release/include/gen--><gdnative project>/include/gen<godot-cpp repo>/godot-headers--><gdnative project>/include/godot-headers- as well as the root
<gdnative project>/include/in the list of inclusions
- Linked the GDNative project against the previously generated static lib (libgodot-cpp.windows.release.64.a)
- Compiled the GDNative project successfully with Mingw-w64 9.0/GCC 11.2.0 into a .dll file
- Pointed the .gdns/.gdnlib boilerplates to resulting .dll
- Loaded up the files in gdscript
Also I partially followed this handy guide: https://aleksandrbazhin.github.io/godot/2021/06/25/GDNative-cpp-in-2k21.html
Any clue as to what could be the cause of all these issues? Maybe I made some obvious, dumb mistake in the above steps, but I genuinely wouldn't know. As far as I can tell, the libraries all compile correctly... that's the extent of my knowledge.
I am in a similar shoes. I would like to use a GDNative module compiled by GCC of MingGW, but the DLL fails to load. When compiling with MSVC, it loads successfully. I am using Godot v3.4.2.stable.official [25eaa2daf] with godot-cpp godot-3.4.2-stable and godot-headers godot-3.4.2-stable.
The error message in Godot is the following:
E 0:00:00.635 open_dynamic_library: Can't open dynamic library: C:/Users/pinting/Dropbox/ipc-test/godot-integration/project/gdnative/windows.mingw64/msys-gdrackclient.dll, error: Error 126: The specified module could not be found.
.
<C++ Error> Condition "!p_library_handle" is true. Returned: ERR_CANT_OPEN
<C++ Source> platform/windows/os_windows.cpp:2353 @ open_dynamic_library()
Both DLL have the following export functions, but the MingGW one have a bunch of others too (see the attached MINGW64 build export functions.txt file).
godot_gdnative_init
godot_gdnative_terminate
godot_nativescript_init
Google Drive link with the built DLLs
SConstruct of the top module.txt SConstruct of the godot-cpp submodule.txt Installed packages.txt MINGW64 build export functions.txt MSVC build export functions.txt
Closing as fixed in 3.5 via godotengine/godot#62173 .
Please leave a comment if you are still encountering this issue after updating godot-cpp to the latest 3.5 branch so we can reopen it in case.