~skeeto/public-inbox

1

Re: How to build and use DLLs on Windows

Eric Farmer
Details
Message ID
<CAAuXPZoSYKr7pBj6au=KXaXKfaS9gRZvd0GLrdF_nJBTvtob8Q@mail.gmail.com>
DKIM signature
pass
Download raw message
Thanks for this; as you say, nice to have this all in one place here,
particularly in the context of w64devkit, since I haven't done this as
portably as I should in the past.

I tend to make one addition to the macro wrappers, prepending an
extern "C" to the API declarations ifdef __cplusplus. This covers what
has been a pretty common use case for this, exposing only a C calling
convention API in the library, that is itself a wrapper around an
implementation that is often C++ under the hood.

Re: How to build and use DLLs on Windows

Details
Message ID
<20210601203328.xwhhda7y7sgfwxh5@nullprogram.com>
In-Reply-To
<CAAuXPZoSYKr7pBj6au=KXaXKfaS9gRZvd0GLrdF_nJBTvtob8Q@mail.gmail.com> (view parent)
DKIM signature
missing
Download raw message
Oh yeah, without a stable ABI there's little hope of using C++ across such 
boundaries. Since w64devkit statically links libstdc++ there are even a 
few gotchas since each side has its own copy of the standard library, 
including static variables, even if it's the exactly same library. For 
instance, modules have distinct std::cout and std::cin objects. I wondered 
if there was something more insidious, so I searched the libstdc++ sources 
and found an interesting case with std::atomic<T>::wait. Here's main.cc:

    #include <atomic>
    #include <thread>

    void sleep_then_set(std::atomic<int> &); // (from library.dll)

    int main()
    {
        std::atomic<int> x = 0;
        std::thread{sleep_then_set, std::ref(x)}.detach();
        x.wait(0);
    }

And here's library.cc:

    #include <atomic>
    #include <thread>

    void sleep_then_set(std::atomic<int> &x)
    {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        x = 1;
        x.notify_one();
    }

Build the library and program:

    c++ -std=c++20 -shared -o library.dll library.cc
    c++ -std=c++20 main.cc library.dll

When I run the executable, it deadlocks. If I move sleep_then_set out of 
the DLL and into the main executable, then it works fine. That's because 
libstdc++ uses a static wait queue internally and this queue isn't shared 
between the DLL and EXE, so they can't await each others atomics.
Reply to thread Export thread (mbox)