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

remove Boost.DLL dependency by doing DLL handling ourselves #1

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions source/reflect.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,7 @@ class compiler_services_data;
// Reflection and meta
//===========================================================================

#ifndef CPPFRONT_LOAD_METAFUNCTION_IMPL_HEADER
#define CPPFRONT_LOAD_METAFUNCTION_IMPL_HEADER "reflect_load_metafunction_never.h"
#endif

#include CPPFRONT_LOAD_METAFUNCTION_IMPL_HEADER
#include "reflect_load_metafunction.h"

#include "parse.h"

Expand Down
6 changes: 1 addition & 5 deletions source/reflect.h2
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@
// Reflection and meta
//===========================================================================

#ifndef CPPFRONT_LOAD_METAFUNCTION_IMPL_HEADER
#define CPPFRONT_LOAD_METAFUNCTION_IMPL_HEADER "reflect_load_metafunction_never.h"
#endif

#include CPPFRONT_LOAD_METAFUNCTION_IMPL_HEADER
#include "reflect_load_metafunction.h"

#include "parse.h"

Expand Down
125 changes: 125 additions & 0 deletions source/reflect_load_metafunction.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#include <cstdlib>
#include <functional>
#include <string>
#include <string_view>
#include <utility>
#include "cpp2util.h"

#ifdef _MSC_VER
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <dlfcn.h>
#endif // _MSC_VER

namespace cpp2::meta {

class dll
{
public:
dll(std::string_view path)
{
#ifdef _MSC_VER
handle_ = static_cast<void*>(LoadLibraryA(path.data()));
#else
handle_ = static_cast<void*>(dlopen(path.data(), RTLD_NOW|RTLD_LOCAL));
#endif // _MSC_VER
// TODO: log if the dll could not be open?
}

~dll() noexcept
{
if(handle_ == nullptr);
return;
#ifdef _MSC_VER
FreeLibrary(static_cast<HMODULE>(handle));
#else
dlclose(handle_);
#endif // _MSC_VER
}

// Uncopyable
dll(dll&) = delete;
dll(dll const&) = delete;
auto operator=(dll const&) -> dll& = delete;

// Movable
dll(dll&& from) noexcept
{
handle_ = from.handle_;
from.handle_ = nullptr;
}

auto operator=(dll&& from) noexcept -> dll&
{
handle_ = from.handle_;
from.handle_ = nullptr;
return *this;
}

auto is_open() noexcept -> bool { return handle_ != nullptr; }

template<typename T>
auto get_alias(std::string_view name) noexcept -> T*
{
void* symbol = nullptr;
#ifdef _MSC_VER
symbol = static_cast<void*>(GetProcAddress(static_cast<HMODULE>(handle_), name.data()));
#else
symbol = dlsym(handle_, name.data());
if(symbol == nullptr)
{
// Some platforms export with additional underscore, so try that.
auto const us_name = std::string("_") + name.data();
symbol = dlsym(handle_, us_name.c_str());
}
#endif // _MSC_VER
// TODO: log if the symbol is not found?
return reinterpret_cast<T*>(symbol);
}
private:
void* handle_{nullptr};
};


// Load metafunction by opening DLL with OS APIs
//
// The ':'-separated library paths
// are read from the environment variable
// 'CPPFRONT_METAFUNCTION_LIBRARIES'
auto load_metafunction(std::string const& name) -> std::function<void(type_declaration&)>
{
auto cpp1_libraries_cstr = std::getenv("CPPFRONT_METAFUNCTION_LIBRARIES");
if (!cpp1_libraries_cstr) {
return {};
}

auto cpp1_libraries = std::string_view{cpp1_libraries_cstr};
auto cpp1_name = "cpp2_metafunction_" + name;

while (!cpp1_libraries.empty())
{
auto colon = cpp1_libraries.find(':');
auto lib_path = cpp1_libraries.substr(0, colon);
cpp1_libraries.remove_prefix(lib_path.size() + unsigned(colon != lib_path.npos));

auto lib = std::make_shared<dll>(lib_path);
if(!lib->is_open())
continue;

if (auto* fun = lib->get_alias<void(void*)>(cpp1_name); fun != nullptr)
{
return [
fun = fun,
lib = lib
DyXel marked this conversation as resolved.
Show resolved Hide resolved
](type_declaration& t)
{
fun(static_cast<void*>(&t));
};
}
}

return {};
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This brings another point up: How to deal with the error logging? (I put some TODOs for now), I immediately identified the error because I had some debug statements to print whatever dlerror gave me, I think there is value in providing that to end-users but I wouldn't know how to integrate that with the rest of cppfront.

This is an important QoI issue that we should discuss with Herb.
I already have 3 different modules authoring metafunctions.
Just imagine how much worse this error message could get
if it listed all metafunctions authored in which libraries (https://cpp2.godbolt.org/z/vqMYYKv5e):

t: @ugh type = { }
main: () = { }
main.cpp2...
main.cpp2(2,1): error: unrecognized metafunction name: ugh
main.cpp2(2,1): error: (temporary alpha limitation) currently the supported names are: interface, polymorphic_base, ordered, weakly_ordered, partially_ordered, copyable, basic_value, value, weakly_ordered_value, partially_ordered_value, struct, enum, flag_enum, union, print

}

}
48 changes: 0 additions & 48 deletions source/reflect_load_metafunction_boost_dll.h

This file was deleted.

26 changes: 0 additions & 26 deletions source/reflect_load_metafunction_never.h

This file was deleted.

7 changes: 4 additions & 3 deletions source/to_cpp1.h
Original file line number Diff line number Diff line change
Expand Up @@ -6448,11 +6448,12 @@ class cppfront
{
auto identifier = print_to_string(*n.identifier);
printer.print_extra(
"\nextern \"C\" constexpr auto cpp2_metafunction_"
"\nextern \"C\" void cpp2_metafunction_"
+ identifier
+ " = &"
+ "(void* t) { "
+ identifier
+ ";"
+ "(*static_cast<cpp2::meta::type_declaration*>(t));"
+ " }"
);
}
}
Expand Down