Skip to content

Commit

Permalink
Initial Code file Commit
Browse files Browse the repository at this point in the history
Added the example files, and updated the README.md file
  • Loading branch information
GrahamCHill committed Jul 9, 2024
1 parent 8d90651 commit 9b3b1ea
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 1 deletion.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
# Cpp-Plugin-Arch
A simple example of the plugin architecture done in C++
Currently the generated library will need to be placed in the same directory as the main executable. I have not done that, but this should show the basic ideas of loading libraries in C++ dynamically on all platforms.

This is more of a simple example, if you need a simple intro to see how you can implement a plugin architecture in C++.
6 changes: 6 additions & 0 deletions example-dynamiclib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 3.28)
project(example_dynamiclib)

set(CMAKE_CXX_STANDARD 17)

add_library(example_dynamiclib SHARED library.cpp)
8 changes: 8 additions & 0 deletions example-dynamiclib/library.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// libmylibrary.cpp
// g++ -dynamiclib -o libmylibrary.dylib libmylibrary.cpp # macOS
// g++ -shared -o libmylibrary.so libmylibrary.cpp # Linux
#include <iostream>

extern "C" void execute() {
std::cout << "Hello from libmylibrary!" << std::endl;
}
6 changes: 6 additions & 0 deletions main-executable/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 3.28)
project(main_executable)

set(CMAKE_CXX_STANDARD 17)

add_executable(main_executable main.cpp)
76 changes: 76 additions & 0 deletions main-executable/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include <iostream>
#include <string>
#include <vector>
#include <filesystem>

#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#else
#include <dlfcn.h>
#endif

namespace fs = std::filesystem;

void loadAndExecuteLibraries(const std::string& directory) {
for (const auto& entry : fs::directory_iterator(directory)) {
std::string path = entry.path().string();

#if defined(_WIN32) || defined(_WIN64)
if (entry.path().extension() == ".dll") {
HINSTANCE handle = LoadLibrary(path.c_str());
if (!handle) {
std::cerr << "Warning: Could not load " << path << ": " << GetLastError() << std::endl;
continue;
}

typedef void (*execute_t)();
execute_t execute = (execute_t)GetProcAddress(handle, "execute");
if (!execute) {
std::cerr << "Warning: Could not find execute in " << path << ": " << GetLastError() << std::endl;
FreeLibrary(handle);
continue;
}

// Call the execute function
execute();

// Free the library
FreeLibrary(handle);
}
#elif defined(__APPLE__) || defined(__linux__)
if (entry.path().extension() == ".dylib" || entry.path().extension() == ".so") {
void* handle = dlopen(path.c_str(), RTLD_LAZY);
if (!handle) {
std::cerr << "Warning: Could not load " << path << ": " << dlerror() << std::endl;
continue;
}

dlerror(); // Clear any existing error
void (*execute)() = (void (*)())dlsym(handle, "execute");
const char* dlsym_error = dlerror();
if (dlsym_error) {
std::cerr << "Warning: Could not find execute in " << path << ": " << dlsym_error << std::endl;
dlclose(handle);
continue;
}

// Call the execute function
execute();

// Close the handle
dlclose(handle);
}
#endif
}
}

int main() {
std::string directory = "./"; // Directory containing .dylib files
loadAndExecuteLibraries(directory);

std::cout << "Continuing execution of the program..." << std::endl;

// Your code here

return 0;
}

0 comments on commit 9b3b1ea

Please sign in to comment.