Merge branch 'master' of https://phabricator.tomicevic.com/diffusion/MG/memgraph
* 'master' of https://phabricator.tomicevic.com/diffusion/MG/memgraph: Much better but not perfect version of dynamic compile and dynamic load code. DynamicLib class and rudimentar example. dynamic lib load work in progress :P cpp program runs compile command, test only code
This commit is contained in:
commit
c9c46f6cd3
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,5 +4,6 @@
|
||||
*.swp
|
||||
*.swo
|
||||
*.out
|
||||
*.so
|
||||
*.dSYM/
|
||||
memgraph
|
||||
|
12
dc/README.md
Normal file
12
dc/README.md
Normal file
@ -0,0 +1,12 @@
|
||||
## Dynamic Code
|
||||
|
||||
```
|
||||
man nm
|
||||
|
||||
cd memgraph/dc
|
||||
cd example
|
||||
clang++ -std=c++1y mysql.cpp -o ../tmp/mysql.so -shared -fPIC
|
||||
clang++ -std=c++1y memsql.cpp -o ../tmp/memsql.so -shared -fPIC
|
||||
cd ..
|
||||
clang++ -std=c++1y test.cpp -o test.out -ldl
|
||||
```
|
65
dc/dynamic_lib.hpp
Normal file
65
dc/dynamic_lib.hpp
Normal file
@ -0,0 +1,65 @@
|
||||
#ifndef MEMGRAPH_DL_DYNAMIC_LIB_HPP
|
||||
#define MEMGRAPH_DL_DYNAMIC_LIB_HPP
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <dlfcn.h>
|
||||
|
||||
template<typename T>
|
||||
class DynamicLib
|
||||
{
|
||||
public:
|
||||
typename T::produce produce_method;
|
||||
typename T::destruct destruct_method;
|
||||
|
||||
DynamicLib(const std::string& lib_path) :
|
||||
lib_path(lib_path)
|
||||
{
|
||||
}
|
||||
|
||||
void load()
|
||||
{
|
||||
load_lib();
|
||||
load_produce_func();
|
||||
load_destruct_func();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string lib_path;
|
||||
void *dynamic_lib;
|
||||
|
||||
void load_lib()
|
||||
{
|
||||
dynamic_lib = dlopen(lib_path.c_str(), RTLD_LAZY);
|
||||
if (!dynamic_lib) {
|
||||
throw std::runtime_error(dlerror());
|
||||
}
|
||||
dlerror();
|
||||
}
|
||||
|
||||
void load_produce_func()
|
||||
{
|
||||
produce_method = (typename T::produce) dlsym(
|
||||
dynamic_lib,
|
||||
T::produce_name.c_str()
|
||||
);
|
||||
const char* dlsym_error = dlerror();
|
||||
if (dlsym_error) {
|
||||
throw std::runtime_error(dlsym_error);
|
||||
}
|
||||
}
|
||||
|
||||
void load_destruct_func()
|
||||
{
|
||||
destruct_method = (typename T::destruct) dlsym(
|
||||
dynamic_lib,
|
||||
T::destruct_name.c_str()
|
||||
);
|
||||
const char *dlsym_error = dlerror();
|
||||
if (dlsym_error) {
|
||||
throw std::runtime_error(dlsym_error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
25
dc/example/db.hpp
Normal file
25
dc/example/db.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef MEMGRAPH_DL_EXAMPLE_DB_HPP
|
||||
#define MEMGRAPH_DL_EXAMPLE_DB_HPP
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class db
|
||||
{
|
||||
public:
|
||||
// If virtual methods don't have = 0 the compiler
|
||||
// won't create appropriate _ZTI symbol inside
|
||||
// the .so lib. That will lead to undefined symbol
|
||||
// error while the library is loading.
|
||||
//
|
||||
// TODO: why?
|
||||
virtual void name() const = 0;
|
||||
virtual void type() const = 0;
|
||||
virtual ~db() {}
|
||||
};
|
||||
|
||||
typedef db* (*produce_t)();
|
||||
typedef void (*destruct_t)(db*);
|
||||
|
||||
#endif
|
28
dc/example/memsql.cpp
Normal file
28
dc/example/memsql.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include "db.hpp"
|
||||
|
||||
class memsql : public db
|
||||
{
|
||||
public:
|
||||
|
||||
void name() const override
|
||||
{
|
||||
cout << "MemSQL" << endl;
|
||||
}
|
||||
|
||||
void type() const override
|
||||
{
|
||||
cout << "InMemory" << endl;
|
||||
}
|
||||
|
||||
~memsql() {}
|
||||
};
|
||||
|
||||
extern "C" db* produce()
|
||||
{
|
||||
return new memsql();
|
||||
}
|
||||
|
||||
extern "C" void destruct(db* p)
|
||||
{
|
||||
delete p;
|
||||
}
|
28
dc/example/mysql.cpp
Normal file
28
dc/example/mysql.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include "db.hpp"
|
||||
|
||||
class mysql : public db
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void name() const
|
||||
{
|
||||
cout << "MySQL" << endl;
|
||||
}
|
||||
|
||||
virtual void type() const
|
||||
{
|
||||
cout << "Relational" << endl;
|
||||
}
|
||||
|
||||
~mysql() {}
|
||||
};
|
||||
|
||||
extern "C" db* produce()
|
||||
{
|
||||
return new mysql();
|
||||
}
|
||||
|
||||
extern "C" void destruct(db* p)
|
||||
{
|
||||
delete p;
|
||||
}
|
28
dc/example/neo4j.cpp
Normal file
28
dc/example/neo4j.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include "db.hpp"
|
||||
|
||||
class neo4j : public db
|
||||
{
|
||||
public:
|
||||
|
||||
void name() const override
|
||||
{
|
||||
cout << "Neo4j" << endl;
|
||||
}
|
||||
|
||||
void type() const override
|
||||
{
|
||||
cout << "Graph" << endl;
|
||||
}
|
||||
|
||||
~neo4j() {}
|
||||
};
|
||||
|
||||
extern "C" db* produce()
|
||||
{
|
||||
return new neo4j();
|
||||
}
|
||||
|
||||
extern "C" void destruct(db* p)
|
||||
{
|
||||
delete p;
|
||||
}
|
28
dc/example/postgresql.cpp
Normal file
28
dc/example/postgresql.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include "db.hpp"
|
||||
|
||||
class postgresql : public db
|
||||
{
|
||||
public:
|
||||
|
||||
void name() const override
|
||||
{
|
||||
cout << "PostgreSQL" << endl;
|
||||
}
|
||||
|
||||
void type() const override
|
||||
{
|
||||
cout << "Relational" << endl;
|
||||
}
|
||||
|
||||
~postgresql() {}
|
||||
};
|
||||
|
||||
extern "C" db* produce()
|
||||
{
|
||||
return new postgresql();
|
||||
}
|
||||
|
||||
extern "C" void destruct(db* p)
|
||||
{
|
||||
delete p;
|
||||
}
|
84
dc/test.cpp
Normal file
84
dc/test.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
#include <cstdlib>
|
||||
#include "example/db.hpp"
|
||||
#include "dynamic_lib.hpp"
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
void write(const std::string& path, const std::string& content)
|
||||
{
|
||||
ofstream stream;
|
||||
stream.open (path.c_str());
|
||||
stream << content;
|
||||
stream.close();
|
||||
}
|
||||
|
||||
std::string join(const std::vector<std::string>& strings, const char *separator)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
std::copy(strings.begin(), strings.end(),
|
||||
std::ostream_iterator<std::string>(oss, separator));
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
std::string prints(const Args&... args)
|
||||
{
|
||||
std::vector<std::string> strings = {args...};
|
||||
return join(strings, " ");
|
||||
}
|
||||
|
||||
// dependent on specific dynamic code
|
||||
// "configuration" of DynamicLib
|
||||
// DynamicLib<MemgraphDynamicLib>
|
||||
class MemgraphDynamicLib
|
||||
{
|
||||
public:
|
||||
const static std::string produce_name;
|
||||
const static std::string destruct_name;
|
||||
typedef produce_t produce;
|
||||
typedef destruct_t destruct;
|
||||
};
|
||||
const std::string MemgraphDynamicLib::produce_name = "produce";
|
||||
const std::string MemgraphDynamicLib::destruct_name = "destruct";
|
||||
|
||||
int main()
|
||||
{
|
||||
// -- compile example
|
||||
|
||||
// string tmp_file_path = "tmp/tmp.cpp";
|
||||
// string tmp_so_path = "tmp/tmp.so";
|
||||
// string for_compile = "#include <iostream>\nint main() { std::cout << \"test\" << std::endl; return 0; }";
|
||||
|
||||
// write(tmp_file_path, for_compile);
|
||||
// string test_command = prints("clang++", tmp_file_path, "-o", "test.out");
|
||||
// system(test_command.c_str());
|
||||
|
||||
// -- end compile example
|
||||
|
||||
// -- load example
|
||||
using db_lib = DynamicLib<MemgraphDynamicLib>;
|
||||
|
||||
db_lib mysql_db("./tmp/mysql.so");
|
||||
mysql_db.load();
|
||||
auto mysql = mysql_db.produce_method();
|
||||
if (mysql) {
|
||||
mysql->name();
|
||||
}
|
||||
mysql_db.destruct_method(mysql);
|
||||
|
||||
db_lib memsql_db("./tmp/memsql.so");
|
||||
memsql_db.load();
|
||||
auto memsql = memsql_db.produce_method();
|
||||
if (memsql) {
|
||||
memsql->name();
|
||||
}
|
||||
memsql_db.destruct_method(memsql);
|
||||
|
||||
return 0;
|
||||
}
|
2
dc/tmp/.gitignore
vendored
Normal file
2
dc/tmp/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/*
|
||||
!.gitignore
|
Loading…
Reference in New Issue
Block a user