Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Usage of included functions resulting in .dll not being found #38961

Open
S3B4S opened this issue May 22, 2020 · 10 comments
Open

Usage of included functions resulting in .dll not being found #38961

S3B4S opened this issue May 22, 2020 · 10 comments

Comments

@S3B4S
Copy link

S3B4S commented May 22, 2020

Godot version: 3.2.1

OS/device including version: Windows 10, build 1903

The issue

Hey, I hope I'm in the right place with this, I've followed the example in the docs for c++: https://docs.godotengine.org/en/stable/tutorials/plugins/gdnative/gdnative-cpp-example.html. This went all right, my next step was to include opencv, so I appended additonal locations to CPPPath, LIBPATH and LIBS in SConstruct: https://github.com/S3B4S/opencv-gdnative/blob/gdnative/SConstruct#L165-L184

When my code only includes the opencv libraries, it will compile and run fine in Godot (below example would have modified src/gdexample.cpp in the example repository);

// This will run fine
 
#include "gdexample.h"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
 
using namespace godot;
using namespace cv;
 
void GDExample::_register_methods() { ... }
 
GDExample::GDExample() { ... }
 
GDExample::~GDExample() { ... }
 
void GDExample::_init() {
    // initialize any variables here
    time_passed = 0.0;
    time_emit = 0.0;
    amplitude = 10.0;
 
    // Mat image = Mat::zeros(300, 600, CV_8UC3);
}

// other unrelated code

But when I do want to use a method from the imported code (so it's the exact same code snippet as above, but the Mat image = Mat::zeros(300, 600, CV_8UC3); line is uncommented), I run into the following error:

ERROR: get_symbol: No valid library handle, can't get symbol from GDNative object
   At: modules/gdnative/gdnative.cpp:483
debugger-agent: Unable to listen on 7020
ERROR: terminate: No valid library handle, can't terminate GDNative object
   At: modules/gdnative/gdnative.cpp:388
ERROR: _update_placeholder: Condition "!script_data" is true.
   At: modules/gdnative/nativescript/nativescript.cpp:92
Running: D:\Program Files (x86)\Godot\Godot_v3.2.1-stable_mono_win64.exe --path C:/Users/kevin/Development/contextproject/Godot --remote-debug 127.0.0.1:6007 --allow_focus_steal_pid 9776 --position 768,420
Godot Engine v3.2.1.stable.mono.official - https://godotengine.org
OpenGL ES 3.0 Renderer: AMD Radeon RX 5700 XT

Mono: Logfile is: C:\Users\kevin\AppData\Roaming/Godot/mono/mono_logs/2020_05_10 21.36.40 (14996).txt
ERROR: Can't open dynamic library: C:/Users/kevin/Development/contextproject/Godot/bin/win64/libgdexample.dll, error: Error 126: The specified module could not be found.
.
   At: platform/windows/os_windows.cpp:2269
ERROR: get_symbol: No valid library handle, can't get symbol from GDNative object
   At: modules/gdnative/gdnative.cpp:483
ERROR: init_library: No nativescript_init in "res://bin/win64/libgdexample.dll" found
   At: modules/gdnative/nativescript/nativescript.cpp:1506

I'm honestly confused by the fact that it's saying it cannot find libgdexample.dll anymore, it's definitely there. When the lines that include OpenCV are commented out it does find the .dll file.

I'm new to this kind of stuff, so I'm not sure if I've overlooked something or that this is unexpected behaviour.


Additional information in case it's needed

I've pushed the project I'm working on to here.

Steps to reproduce:

Assuming that OpenCV is installed & OPENCV_DIR environment variable is set.

  1. I've followed the instructions described in the documentation.
  2. Apply adjustments described above.
  3. Run scons platform=windows, this should output a libgdexample.dll among other files in <Godotproject>/bin/win64
  4. Open the godot project and run the main scene
  5. In case OpenCV functions are used, above errors should appear.
@S3B4S
Copy link
Author

S3B4S commented May 22, 2020

Some more information as I had 2 teammates reproduce the error, one is on MacOS, the other is on Windows. The person on MacOS is not able to reproduce the error, they follow the same steps I did and it's successfully working for them. They've also cloned the project that I was working on and that is also still working for them. The other person on Windows does run into the same error that I do. So I'm starting to think it might have to with either the environment or build tools.

So some information regarding this environment;

  • I've been using the terminal of Visual Studio Community 2019 to run scons platform=windows. Setting the environment to x64.
  • Using SCons 3.1.2
  • Using OpenCV 4.3.0

@S3B4S
Copy link
Author

S3B4S commented May 22, 2020

By now I've attempted to do this with CMake, but that unfortunately results in the exact same issue as described above.

The CMakeLists.txt is in a build/ directory that has been added to the root of the repo (structure still same as the example repo).

Steps to reproduce

  1. cd build/
  2. cmake .
  3. This will generate a .dll with additional files, copy all of those over to <godot-project>/bin/win64/
  4. If OpenCV functions are used, below error is shown

CMakeLists.txt:

cmake_minimum_required(VERSION 3.1...3.15)

if(${CMAKE_VERSION} VERSION_LESS 3.12)
  cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
endif()

# set the project name
project(TouchThaBomb  VERSION 0.1
                      DESCRIPTION "Defuse bomb game with hand tracking"
                      LANGUAGES CXX)


# https://cmake.org/cmake/help/latest/command/find_package.html#search-procedure 
find_package(OpenCV 4.3 EXACT REQUIRED PATHS /OpenCV/opencv-4.3.0-vc16/)
include_directories(AFTER "${OpenCV_INCLUDE_DIRS}" "include")
link_libraries(${OpenCV_LIBS})

link_libraries("../godot-cpp/bin/libgodot-cpp.windows.debug.64")

# create the .dll
#file(GLOB source_list "src/*.h" "src/*.cpp")
add_library(libgdexample SHARED "../src/gdexample.cpp" "../src/gdlibrary.cpp")

include_directories(
  "../godot-cpp/godot_headers/"
  "../godot-cpp/include/"
  "../godot-cpp/include/core/"
  "../godot-cpp/include/gen/"
  "../godot-cpp/bin/"
)

When my code only includes the opencv libraries, it will compile and run fine in Godot;
But when I do want to use a method from the imported code (so it's the exact same code snippet as above, but the Mat image = Mat::zeros(300, 600, CV_8UC3); line is uncommented), I run into the following error:

Remains the exact same, the error is as follows:

ERROR: Can't open dynamic library: C:/Users/kevin/Development/contextproject/Godot/bin/win64/libgdexample.dll, error: Error 126: The specified module could not be found.
.
   At: platform/windows/os_windows.cpp:2269
ERROR: get_symbol: No valid library handle, can't get symbol from GDNative object
   At: modules/gdnative/gdnative.cpp:483
ERROR: init_library: No nativescript_init in "res://bin/win64/libgdexample.dll" found
   At: modules/gdnative/nativescript/nativescript.cpp:1506
ERROR: _update_placeholder: Condition "!script_data" is true.
   At: modules/gdnative/nativescript/nativescript.cpp:92
ERROR: _update_placeholder: Condition "!script_data" is true.
   At: modules/gdnative/nativescript/nativescript.cpp:92
Running: D:\Program Files (x86)\Godot\Godot_v3.2.1-stable_mono_win64.exe --path C:/Users/kevin/Development/contextproject/Godot --remote-debug 127.0.0.1:6007 --allow_focus_steal_pid 5300 --position 768,420
Godot Engine v3.2.1.stable.mono.official - https://godotengine.org
OpenGL ES 3.0 Renderer: AMD Radeon RX 5700 XT

Mono: Logfile is: C:\Users\kevin\AppData\Roaming/Godot/mono/mono_logs/2020_05_18 19.09.43 (9464).txt
ERROR: Can't open dynamic library: C:/Users/kevin/Development/contextproject/Godot/bin/win64/libgdexample.dll, error: Error 126: The specified module could not be found.
.
   At: platform/windows/os_windows.cpp:2269
ERROR: get_symbol: No valid library handle, can't get symbol from GDNative object
   At: modules/gdnative/gdnative.cpp:483
ERROR: init_library: No nativescript_init in "res://bin/win64/libgdexample.dll" found
   At: modules/gdnative/nativescript/nativescript.cpp:1506

@BastiaanOlij
Copy link
Contributor

For some reason it can't open the DLL that is created:

ERROR: Can't open dynamic library: C:/Users/kevin/Development/contextproject/Godot/bin/win64/libgdexample.dll, error: Error 126: The specified module could not be found. Both in this version and your original version. The rest of the errors are flow on effects.

Assuming it has compiled the DLL and it is placed in that folder, it could be that it can't load OpenCV itself as a dependency. You need to make sure the opencv dll(s) are also placed in the bin/win64 folder and that you name those dlls in your gdnlib file in the dependencies section

@S3B4S
Copy link
Author

S3B4S commented May 24, 2020

Hey, thanks for responding.

We're actually not including any opencv dll(s), we're including .lib files instead, from my understanding these files should be inlined in the created libgdexample.dll right? Or should we also include the opencv dll(s) as found in <path-to-opencv>/bin/?

For ease, I've uploaded the project that I'm using to reproduce this. https://github.com/S3B4S/opencv-gdnative/tree/gdnative. In the repository I've added a example-opencv-dependency.txt file that shows the structure of the opencv (4.3.0) dependency so you can see what I'm talking about.

@S3B4S
Copy link
Author

S3B4S commented May 24, 2020

Though, by now I'm running in a new error that might provide more information. If I try to include an additional line in gdexample.cpp (this one: https://github.com/S3B4S/opencv-gdnative/blob/gdnative/src/gdexample.cpp#L34). I get the following error:

scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
link /nologo -DEBUG /dll /out:Godot\bin\win64\libgdexample.dll /implib:Godot\bin\win64\libgdexample.lib /LIBPATH:godot-cpp\bin /LIBPATH:D:\OpenCV\opencv-4.3.0-vc16\build\lib libgodot-cpp.windows.debug.64.lib opencv_calib3d430.lib opencv_core430.lib opencv_dnn430.lib opencv_features2d430.lib opencv_flann430.lib opencv_gapi430.lib opencv_highgui430.lib opencv_imgcodecs430.lib opencv_imgproc430.lib opencv_ml430.lib opencv_objdetect430.lib opencv_photo430.lib opencv_stitching430.lib opencv_video430.lib opencv_videoio430.lib src\gdexample.obj src\gdlibrary.obj
   Creating library Godot\bin\win64\libgdexample.lib and object Godot\bin\win64\libgdexample.exp
gdexample.obj : error LNK2019: unresolved external symbol "void __cdecl cv::circle(class cv::debug_build_guard::_InputOutputArray const &,class cv::Point_<int>,int,class cv::Scalar_<double> const &,int,int,int)" (?circle@cv@@YAXAEBV_InputOutputArray@debug_build_guard@1@V?$Point_@H@1@HAEBV?$Scalar_@N@1@HHH@Z) referenced in function "public: void __cdecl godot::GDExample::_init(void)" (?_init@GDExample@godot@@QEAAXXZ)
Godot\bin\win64\libgdexample.dll : fatal error LNK1120: 1 unresolved externals
scons: *** [Godot\bin\win64\libgdexample.dll] Error 1120
scons: building terminated because of errors.

So usually this means that it cannot find certain header files and/or libraries from my understanding, but I cannot find what I'm missing here. I think I've set it up fine in the SConstruct.

I've also set up a seperate project with only opencv, using Visual Studio and when I set these same locations it worked fine when building with Visual Studio. (For more information on how I did this project, I followed the steps described here).

So I don't feel like there's something wrong with the locations themselves, however I might miss something else that's needed for building a .dll perhaps?

@BastiaanOlij
Copy link
Contributor

That all depends on whether you've compiled OpenCV as a static library or not. If it is compiled as a static library the .lib file contains all. If you've compiled it as a dynamic library the .lib file only contains the glue that allows you to use the OpenCV dll and the dll needs to be included.

The new error you're getting means that you are calling the circle function in the OpenCV library but that it doesn't know this function. That suggest the library file isn't being included correctly. Makes no sense though, from what I understand circle is a core function of OpenCV and you are including the core library.. Unless there is some other reason it skips that code in the SConstruct file..

@S3B4S
Copy link
Author

S3B4S commented May 25, 2020

Okay that was insightful, since the libraries I'm using are pre-built ones downloaded from here, so I went and checked if they were dynamic or static by running lib /list <name>.lib on one of the libs (source: https://stackoverflow.com/questions/6402586/know-if-lib-is-static-or-import)

So running

$ lib  /list opencv_calib3d430.lib

gave me the output of

opencv_calib3d430.dll

... 814 times 😆.

I think it seems fair to conclude then that this means these .lib's are dynamic as you mentioned it, and I'd need to include all the .dll files as referenced by the .lib files in win64/bin/ and declare them as dependencies.

The circle not being found is indeed very strange, I will keep digging around about that, in any case I wanted to report above findings.

@S3B4S
Copy link
Author

S3B4S commented May 25, 2020

Regarding the "circle function not being found", when I build with CMake this issue does not appear. I'm succesfully able to build the same source files. So with this out of the way, I tried to see if adding the .dll files found in the OpenCV bin/ and declaring them as dependencies would do the trick:

But unfortunately, the error still remains 🤔

@follower
Copy link
Contributor

Oh, I hadn't realised there was an issue opened for this here too.

FYI, I replied to your other issue in case it's still useful: godotengine/godot-cpp#403 (comment)

I've also subsequently discovered that GDNative does its own (redundant?) dynamic library path manipulation before calling the open_dynamic_library() function.

I've also discovered what appears to be an edge case problem that occurs if you try to run an exported .exe while it's in the root of your project structure (or equivalent location or if you're using the CLI to run the exe while the current directory is the project? (I'm still confirming the exact situation)) due to this check:

if (!FileAccess::exists(path)) {
//this code exists so gdnative can load .dll files from within the executable path
path = get_executable_path().get_base_dir().plus_file(p_path.get_file());
}

AFAICT the !FileAccess::exists(path) check shouldn't occur in exported executables because it can access paths that the (Windows OS) DLL loading code is...unaware of, I guess.

I think if the path is converted to an absolute path first then both entities would see things the same way--but that may have its own issues.

Anyway, I only mention that here because it was a bizarre scenario where I knew I'd had a particular executable run & find its DLL dependencies previously but now it couldn't--and it turned out to be related to now being in the project directory on the command line.

Given all this, I'd recommend you use a file access logging tool to find out what paths are actually being accessed. Since I was doing this investigation on a Mac with WINE (it's a long story... :D ) I was able to use opensnoop, a DTrace-based tool.

@3ddelano
Copy link

TLDR: Same issue here on Godot 3.3.4 when trying to call a method of DiscordGameSDK from a C++ gdnative project. It works fine if I define any variable which is of a type from the DiscordGameSDK but as soon as I try to call any method from it I get the same error "cant open dynamic library..." in the Godot editor.

Godot version: 3.3.4
godot-cpp: Branch 3.3
OS/device including version: Windows 10 x64 21H1 19043.1415

What I have so far

  1. A basic gdnative C++ project which includes the discord_game_sdk
  2. A compiled version of the said project to a .dll file (no errors in compilation)
  3. The compiled library provided by 3rd party (discord_game_sdk.dll)
  4. A simple godot project which use this gdnative library and nativescript and includes my dll and, as dependency the 3rd party dll.

I get the error "Cant open dynamic library" in the Godot editor only when the c++ project trys to call any method from discord_Game_sdk.
[attached godot project files]
Gdnative_cpp_project.zip

@Calinou Calinou added the bug label Jan 10, 2022
@Calinou Calinou added this to the 3.5 milestone Jan 10, 2022
@KoBeWi KoBeWi modified the milestones: 3.5, 3.x Apr 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants