added a C++ API
This commit is contained in:
parent
6d73e7898e
commit
de7a01d322
@ -84,28 +84,48 @@ endif
|
|||||||
|
|
||||||
.PHONY: build-executable
|
.PHONY: build-executable
|
||||||
build: build-executable
|
build: build-executable
|
||||||
build-executable: $(bindir)/executable $(bindir)/executable-cpp
|
build-executable: $(bindir)/executable $(bindir)/executable-as-cxx $(bindir)/executable-as-cxx11 $(bindir)/executable-cxx $(bindir)/executable-cxx11
|
||||||
|
|
||||||
$(bindir)/executable: $(srcdir)/whereami.c $(srcdir)/whereami.h $(exampledir)/executable.c
|
$(bindir)/executable: $(srcdir)/whereami.c $(srcdir)/whereami.h $(exampledir)/executable.c
|
||||||
mkdir -p $(@D)
|
mkdir -p $(@D)
|
||||||
$(CC) -I $(srcdir) $(CPPFLAGS) $(CFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -o $@
|
$(CC) -I $(srcdir) $(CPPFLAGS) $(CFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -o $@
|
||||||
$(if $(postbuild),$(postbuild) $@)
|
$(if $(postbuild),$(postbuild) $@)
|
||||||
|
|
||||||
$(bindir)/executable-cpp: $(srcdir)/whereami.c $(srcdir)/whereami.h $(exampledir)/executable.c
|
$(bindir)/executable-as-cxx: $(srcdir)/whereami.c $(srcdir)/whereami.h $(exampledir)/executable.c
|
||||||
mkdir -p $(@D)
|
mkdir -p $(@D)
|
||||||
$(CXX) -x c++ -I $(srcdir) $(CPPFLAGS) $(CXXFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -o $@
|
$(CXX) -std=c++03 -x c++ -I $(srcdir) $(CPPFLAGS) $(CXXFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -o $@
|
||||||
|
$(if $(postbuild),$(postbuild) $@)
|
||||||
|
|
||||||
|
$(bindir)/executable-as-cxx11: $(srcdir)/whereami.c $(srcdir)/whereami.h $(exampledir)/executable.c
|
||||||
|
mkdir -p $(@D)
|
||||||
|
$(CXX) -std=c++11 -x c++ -I $(srcdir) $(CPPFLAGS) $(CXXFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -o $@
|
||||||
|
$(if $(postbuild),$(postbuild) $@)
|
||||||
|
|
||||||
|
$(bindir)/executable-cxx: $(srcdir)/whereami++.cpp $(srcdir)/whereami++.h $(exampledir)/executable.cpp
|
||||||
|
mkdir -p $(@D)
|
||||||
|
$(CXX) -std=c++03 -x c++ -I $(srcdir) $(CPPFLAGS) $(CXXFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -o $@
|
||||||
|
$(if $(postbuild),$(postbuild) $@)
|
||||||
|
|
||||||
|
$(bindir)/executable-cxx11: $(srcdir)/whereami++.cpp $(srcdir)/whereami++.h $(exampledir)/executable.cpp
|
||||||
|
mkdir -p $(@D)
|
||||||
|
$(CXX) -std=c++11 -x c++ -I $(srcdir) $(CPPFLAGS) $(CXXFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -o $@
|
||||||
$(if $(postbuild),$(postbuild) $@)
|
$(if $(postbuild),$(postbuild) $@)
|
||||||
|
|
||||||
.PHONY: build-library
|
.PHONY: build-library
|
||||||
build: build-library
|
build: build-library
|
||||||
build-library: $(bindir)/library$(libsuffix) $(bindir)/library-cpp$(libsuffix)
|
build-library: $(bindir)/library$(libsuffix) $(bindir)/library-as-cxx$(libsuffix) $(bindir)/library-cxx$(libsuffix)
|
||||||
|
|
||||||
$(bindir)/library$(libsuffix): $(srcdir)/whereami.c $(srcdir)/whereami.h $(exampledir)/library.c
|
$(bindir)/library$(libsuffix): $(srcdir)/whereami.c $(srcdir)/whereami.h $(exampledir)/library.c
|
||||||
mkdir -p $(@D)
|
mkdir -p $(@D)
|
||||||
$(CC) -I $(srcdir) $(CPPFLAGS) $(CFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -shared -o $@
|
$(CC) -I $(srcdir) $(CPPFLAGS) $(CFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -shared -o $@
|
||||||
$(if $(postbuild),$(postbuild) $@)
|
$(if $(postbuild),$(postbuild) $@)
|
||||||
|
|
||||||
$(bindir)/library-cpp$(libsuffix): $(srcdir)/whereami.c $(srcdir)/whereami.h $(exampledir)/library.c
|
$(bindir)/library-as-cxx$(libsuffix): $(srcdir)/whereami.c $(srcdir)/whereami.h $(exampledir)/library.c
|
||||||
|
mkdir -p $(@D)
|
||||||
|
$(CXX) -x c++ -I $(srcdir) $(CPPFLAGS) $(CXXFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -shared -o $@
|
||||||
|
$(if $(postbuild),$(postbuild) $@)
|
||||||
|
|
||||||
|
$(bindir)/library-cxx$(libsuffix): $(srcdir)/whereami++.cpp $(srcdir)/whereami++.h $(exampledir)/library.cpp
|
||||||
mkdir -p $(@D)
|
mkdir -p $(@D)
|
||||||
$(CXX) -x c++ -I $(srcdir) $(CPPFLAGS) $(CXXFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -shared -o $@
|
$(CXX) -x c++ -I $(srcdir) $(CPPFLAGS) $(CXXFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -shared -o $@
|
||||||
$(if $(postbuild),$(postbuild) $@)
|
$(if $(postbuild),$(postbuild) $@)
|
||||||
|
101
example/executable.cpp
Normal file
101
example/executable.cpp
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <whereami++.h>
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(push, 3)
|
||||||
|
#endif
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#define RTLD_LAZY 1
|
||||||
|
#define RTLD_NOW 2
|
||||||
|
#define RTLD_GLOBAL 4
|
||||||
|
#define RTLD_LOCAL 8
|
||||||
|
|
||||||
|
static void* dlopen(const char* fileName, int mode)
|
||||||
|
{
|
||||||
|
wchar_t buffer[MAX_PATH];
|
||||||
|
|
||||||
|
if (MultiByteToWideChar(CP_UTF8, 0, fileName, -1, buffer, sizeof(buffer) / sizeof(*buffer)))
|
||||||
|
{
|
||||||
|
wchar_t buffer_[MAX_PATH];
|
||||||
|
|
||||||
|
GetFullPathNameW(buffer, sizeof(buffer_) / sizeof(*buffer_), buffer_, NULL);
|
||||||
|
|
||||||
|
return (void*)LoadLibraryW(buffer_);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dlclose(void* handle)
|
||||||
|
{
|
||||||
|
return FreeLibrary((HMODULE)handle) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* dlerror(void)
|
||||||
|
{
|
||||||
|
DWORD error;
|
||||||
|
|
||||||
|
error = GetLastError();
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
static char message[1024];
|
||||||
|
|
||||||
|
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), message, sizeof(message), NULL);
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "no error";
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
std::cout << "executable path: " << whereami::getExecutablePath() << std::endl;
|
||||||
|
whereami::whereami_path_t executablePath = whereami::getExecutablePath();
|
||||||
|
std::cout << " dirname: " << executablePath.dirname() << std::endl;
|
||||||
|
std::cout << " basename: " << executablePath.basename() << std::endl;
|
||||||
|
|
||||||
|
std::cout << "module path: " << whereami::getModulePath() << std::endl;
|
||||||
|
whereami::whereami_path_t modulePath = whereami::getModulePath();
|
||||||
|
std::cout << " dirname: " << modulePath.dirname() << std::endl;
|
||||||
|
std::cout << " basename: " << modulePath.basename() << std::endl;
|
||||||
|
|
||||||
|
for (int i = 1; i < argc; ++i)
|
||||||
|
{
|
||||||
|
std::string prefix = "--load-library=";
|
||||||
|
std::string arg = std::string(argv[i]);
|
||||||
|
|
||||||
|
if (arg.compare(0, prefix.length(), prefix) == 0)
|
||||||
|
{
|
||||||
|
std::string name = arg.substr(prefix.length());
|
||||||
|
void* handle;
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
handle = dlopen(name.c_str(), RTLD_NOW);
|
||||||
|
if (!handle)
|
||||||
|
std::cout << "failed to load library: " << dlerror() << std::endl;
|
||||||
|
|
||||||
|
if (handle)
|
||||||
|
dlclose(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
61
example/library.cpp
Normal file
61
example/library.cpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <whereami++.h>
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && !defined(_WIN32)
|
||||||
|
__attribute__((constructor))
|
||||||
|
#endif
|
||||||
|
static void load()
|
||||||
|
{
|
||||||
|
std::cout << "library loaded" << std::endl;
|
||||||
|
|
||||||
|
std::cout << "executable path: " << whereami::getExecutablePath() << std::endl;
|
||||||
|
whereami::whereami_path_t executablePath = whereami::getExecutablePath();
|
||||||
|
std::cout << " dirname: " << executablePath.dirname() << std::endl;
|
||||||
|
std::cout << " basename: " << executablePath.basename() << std::endl;
|
||||||
|
|
||||||
|
std::cout << "module path: " << whereami::getModulePath() << std::endl;
|
||||||
|
whereami::whereami_path_t modulePath = whereami::getModulePath();
|
||||||
|
std::cout << " dirname: " << modulePath.dirname() << std::endl;
|
||||||
|
std::cout << " basename: " << modulePath.basename() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && !defined(_WIN32)
|
||||||
|
__attribute__((destructor))
|
||||||
|
#endif
|
||||||
|
static void unload()
|
||||||
|
{
|
||||||
|
std::cout << "library unloaded" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(push, 3)
|
||||||
|
#endif
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
||||||
|
{
|
||||||
|
switch (ul_reason_for_call)
|
||||||
|
{
|
||||||
|
case DLL_PROCESS_ATTACH:
|
||||||
|
load();
|
||||||
|
break;
|
||||||
|
case DLL_THREAD_ATTACH:
|
||||||
|
break;
|
||||||
|
case DLL_THREAD_DETACH:
|
||||||
|
break;
|
||||||
|
case DLL_PROCESS_DETACH:
|
||||||
|
unload();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
104
src/whereami++.cpp
Normal file
104
src/whereami++.cpp
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
// (‑●‑●)> released under the WTFPL v2 license, by Gregory Pakosz (@gpakosz)
|
||||||
|
// https://github.com/gpakosz/whereami
|
||||||
|
|
||||||
|
// in case you want to #include "whereami++.cpp" in a larger compilation unit
|
||||||
|
#if !defined(WHEREAMIPP_H)
|
||||||
|
#include <whereami++.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace whereami {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
#define WHEREAMI_H
|
||||||
|
#define WAI_FUNCSPEC
|
||||||
|
#define WAI_PREFIX(function) function
|
||||||
|
#include "whereami.c"
|
||||||
|
}
|
||||||
|
|
||||||
|
whereami_string_t whereami_path_t::dirname() const
|
||||||
|
{
|
||||||
|
return path.substr(0, dirname_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
whereami_string_t whereami_path_t::basename() const
|
||||||
|
{
|
||||||
|
return path.substr(dirname_length + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(WHEREAMI_CXX11)
|
||||||
|
whereami_path_t::operator whereami_string_t() &&
|
||||||
|
{
|
||||||
|
return std::move(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
whereami_path_t::operator whereami_string_t() const &
|
||||||
|
{
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
whereami_path_t::operator const whereami_string_t&() const
|
||||||
|
{
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WHEREAMI_CXX11)
|
||||||
|
whereami_path_t::whereami_path_t(whereami_string_t&& path, int dirname_length) noexcept
|
||||||
|
: path(std::move(path)), dirname_length(dirname_length)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
whereami_path_t::whereami_path_t(whereami_string_t& path, int dirname_length)
|
||||||
|
: path(path), dirname_length(dirname_length)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(WHEREAMI_DISABLE_OSTREAM)
|
||||||
|
std::ostream& operator<<(std::ostream& os, const whereami_path_t& path)
|
||||||
|
{
|
||||||
|
return os << path.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
WAI_FUNCSPEC
|
||||||
|
whereami_path_t getExecutablePath()
|
||||||
|
{
|
||||||
|
whereami_string_t path;
|
||||||
|
int dirname_length = -1;
|
||||||
|
|
||||||
|
int length = getExecutablePath(0, 0, 0);
|
||||||
|
if (length != -1)
|
||||||
|
{
|
||||||
|
path.resize(length);
|
||||||
|
getExecutablePath(&path[0], length, &dirname_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(WHEREAMI_CXX11)
|
||||||
|
return whereami_path_t(std::move(path), dirname_length);
|
||||||
|
#else
|
||||||
|
return whereami_path_t(path, dirname_length);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
WAI_FUNCSPEC
|
||||||
|
whereami_path_t getModulePath()
|
||||||
|
{
|
||||||
|
whereami_string_t path;
|
||||||
|
int dirname_length = -1;
|
||||||
|
|
||||||
|
int length = getModulePath(0, 0, 0);
|
||||||
|
if (length != -1)
|
||||||
|
{
|
||||||
|
path.resize(length);
|
||||||
|
getModulePath(&path[0], length, &dirname_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(WHEREAMI_CXX11)
|
||||||
|
return whereami_path_t(std::move(path), dirname_length);
|
||||||
|
#else
|
||||||
|
return whereami_path_t(path, dirname_length);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace whereami
|
67
src/whereami++.h
Normal file
67
src/whereami++.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
// (‑●‑●)> released under the WTFPL v2 license, by Gregory Pakosz (@gpakosz)
|
||||||
|
// https://github.com/gpakosz/whereami
|
||||||
|
|
||||||
|
#ifndef WHEREAMIPP_H
|
||||||
|
#define WHEREAMIPP_H
|
||||||
|
|
||||||
|
#if !defined(WHEREAMI_STRING_T)
|
||||||
|
#include <string>
|
||||||
|
typedef std::string whereami_string_t;
|
||||||
|
#else
|
||||||
|
typedef WHEREAMI_STRING_T whereami_string_t;
|
||||||
|
#endif
|
||||||
|
#if !defined(WHEREAMI_DISABLE_OSTREAM)
|
||||||
|
#include <ostream>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined (__cplusplus) && (__cplusplus > 199711L)) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 150020706))
|
||||||
|
#define WHEREAMI_CXX11
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace whereami {
|
||||||
|
|
||||||
|
class whereami_path_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
#if defined(WHEREAMI_CXX11)
|
||||||
|
operator whereami_string_t() &&;
|
||||||
|
operator whereami_string_t() const &;
|
||||||
|
#else
|
||||||
|
operator const whereami_string_t&() const;
|
||||||
|
#endif
|
||||||
|
whereami_string_t dirname() const;
|
||||||
|
whereami_string_t basename() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
whereami_path_t();
|
||||||
|
|
||||||
|
#if defined(WHEREAMI_CXX11)
|
||||||
|
whereami_path_t(whereami_string_t&& path, int dirname_length) noexcept;
|
||||||
|
#else
|
||||||
|
whereami_path_t(whereami_string_t& path, int dirname_length);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
friend whereami_path_t getExecutablePath();
|
||||||
|
friend whereami_path_t getModulePath();
|
||||||
|
#if !defined(WHEREAMI_DISABLE_OSTREAM)
|
||||||
|
friend std::ostream& operator<<(std::ostream& os, const whereami_path_t& path);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
whereami_string_t path;
|
||||||
|
int dirname_length;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the path to the current executable.
|
||||||
|
*/
|
||||||
|
whereami_path_t getExecutablePath();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the path to the current module.
|
||||||
|
*/
|
||||||
|
whereami_path_t getModulePath();
|
||||||
|
|
||||||
|
} // namespace whereami
|
||||||
|
|
||||||
|
#endif // #ifndef WHEREAMIPP_H
|
||||||
|
|
@ -10,6 +10,13 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef WAI_FUNCSPEC
|
||||||
|
#define WAI_FUNCSPEC
|
||||||
|
#endif
|
||||||
|
#ifndef WAI_PREFIX
|
||||||
|
#define WAI_PREFIX(function) wai_##function
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(WAI_MALLOC) || !defined(WAI_FREE) || !defined(WAI_REALLOC)
|
#if !defined(WAI_MALLOC) || !defined(WAI_FREE) || !defined(WAI_REALLOC)
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -38,7 +38,7 @@ WAI_FUNCSPEC
|
|||||||
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length);
|
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the path to the current module
|
* Returns the path to the current module.
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* - first call `int length = wai_getModulePath(NULL, 0, NULL);` to retrieve
|
* - first call `int length = wai_getModulePath(NULL, 0, NULL);` to retrieve
|
||||||
|
Loading…
Reference in New Issue
Block a user