glfwGetTime work fine in lib but return 0 in dll

glfwGetTime work fine in dll but return 0 in executable in my project, so I create a minimal reproduction project. https://github.com/CheapMeow/glfw-get-time-test

But in this project, I find glfwGetTime work fine in lib but return 0 in dll. It is confusing, why?

My minimal project intro:

glfw-in-dll folder contains project that uses glfwGetTime in dll.

glfw-in-dll\src\runtime\time_utils.h

#pragma once

#include "macro.h"

#include <GLFW/glfw3.h>

class LIBRARY_API Time
{
public:
    static float GetTime() { return glfwGetTime(); }
};

glfw-in-lib folder contains project that uses glfwGetTime in lib.

glfw-in-lib\src\runtime\time_utils.h

#pragma once

#include <GLFW/glfw3.h>

class Time
{
public:
    static float GetTime() { return glfwGetTime(); }
};

Both projects print glfwGetTime() in library.

void Runtime::PrintTime() { std::cout << "Runtime: " << Time::GetTime() << "s" << std::endl; }

Both projects print glfwGetTime() in executable.

int main()
{
    if (glfwInit())
        std::cout << "Editor: GLFW init success." << std::endl;
    else
        std::cout << "Editor: GLFW init fail." << std::endl;

    Runtime runtime;

    std::size_t output_count     = 0;
    std::size_t max_output_count = 100;
    while (1)
    {
        randomSleep(50.0, 100.0);
        std::cout << "Editor: " << Time::GetTime() << "s" << std::endl;
        runtime.PrintTime();

        output_count++;
        if (output_count >= max_output_count)
            break;
    }

    return 0;
}

glfw-in-dll output

Editor: Waited for 87.1732 ms.
Editor: 0.723095s
Runtime: 0s
Editor: Waited for 69.2278 ms.
Editor: 0.800194s
Runtime: 0s
Editor: Waited for 99.8627 ms.
Editor: 0.908878s
Runtime: 0s
Editor: Waited for 70.4661 ms.
Editor: 0.985678s
Runtime: 0s
Editor: Waited for 83.087 ms.
Editor: 1.07766s
Runtime: 0s

glfw-in-lib output

Editor: Waited for 74.9078 ms.
Editor: 0.833975s
Runtime: 0.834277s
Editor: Waited for 75.4188 ms.
Editor: 0.910967s
Runtime: 0.911241s
Editor: Waited for 75.6444 ms.
Editor: 0.990564s
Runtime: 0.990761s
Editor: Waited for 82.5768 ms.
Editor: 1.08412s
Runtime: 1.08442s
Editor: Waited for 80.6122 ms.
Editor: 1.17785s
Runtime: 1.17831s

The reason might be singleton class will have one instance in executable and another instance in dll. I am not sure.

This is a bit weird.

When you link GLFW into a shared library/DLL you are effectively doing the same thing as building and linking GLFW as a shared library/DLL itself, and so would normally need to use the GLFW_DLL build macro as per the documentation.

However you export your own class, so this should work, but the function definition is static and inline (defined in the class header declaration).

The simplest way around this would be to build GLFW as shared when using it with shared libraries (and define the GLFW_DLL macro from projects using it). A more complex approach would be to ensure GLFW is built with the correct import/export macros when linked into a DLL.

In CMakeLists.txt, I add GLFW_DLL macro but it doesn’t help.

if(NOT TARGET glfw)
    option(GLFW_BUILD_EXAMPLES "" OFF)
    option(GLFW_BUILD_TESTS "" OFF)
    option(GLFW_BUILD_DOCS "" OFF)
    option(GLFW_INSTALL "" OFF)
    option(GLFW_DLL "" ON)
    add_subdirectory(${CMAKE_SOURCE_DIR}/../glfw glfw)
endif()

Apologies my first paragraph is misleading, and should have added more information.

The correct solution is the final paragraph:

The simplest way around this would be to build GLFW as shared when using it with shared libraries (and define the GLFW_DLL macro from projects using it). A more complex approach would be to ensure GLFW is built with the correct import/export macros when linked into a DLL.

Ok, I know, I should take some steps to ensure glfw is built to dll, if I link glfw to a dll.

I add BUILD_SHARED_LIBS option then solve the problem! Thank you!

if(NOT TARGET glfw)
    option(GLFW_BUILD_EXAMPLES "" OFF)
    option(GLFW_BUILD_TESTS "" OFF)
    option(GLFW_BUILD_DOCS "" OFF)
    option(GLFW_INSTALL "" OFF)
    option(GLFW_DLL "" ON)
    option(BUILD_SHARED_LIBS "" ON)
    add_subdirectory(${CMAKE_SOURCE_DIR}/../glfw glfw)
endif()