From e0407d9f5f8ac63ebcb35dead65964554cae6cf4 Mon Sep 17 00:00:00 2001 From: mrbesen Date: Thu, 20 Feb 2020 12:21:43 +0100 Subject: [PATCH] endlich --- .gitignore | 5 + Makefile | 4 +- inc/cppplugin.h | 11 -- inc/libplugin.h | 23 +++ inc/plugin.h | 37 ++++ runall.sh | 1 + src/main/cpp/src/libplugin.cpp | 158 ++++++++++++++---- .../java/de/mrbesen/cppplugins/CppLoader.java | 2 +- .../java/de/mrbesen/cppplugins/CppPlugin.java | 8 +- .../de/mrbesen/cppplugins/CppPlugins.java | 7 +- testplugins/verysimpleplugin/Makefile | 6 +- testplugins/verysimpleplugin/src/plugin.cpp | 8 +- 12 files changed, 215 insertions(+), 55 deletions(-) delete mode 100644 inc/cppplugin.h create mode 100644 inc/libplugin.h create mode 100644 inc/plugin.h diff --git a/.gitignore b/.gitignore index f67c36e..5286180 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,8 @@ target *.jar .idea/ .vscode/ + +#eclipse stuff +.cproject +.project +.settings/ \ No newline at end of file diff --git a/Makefile b/Makefile index ead6445..a2e57c4 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CFLAGS = -Wall -pedantic-errors -std=c++17 -g #-O2 SRCDIR = src/main/cpp/src/ BUILDDIR = target/ INCDIR = src/main/cpp/inc/ -LDFLAGS = -I/usr/lib/jvm/java-8-openjdk-amd64/include/ -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux/ -I$(INCDIR) -Iinc/ +LDFLAGS = -I/usr/lib/jvm/java-8-openjdk-amd64/include/ -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux/ -I$(INCDIR) -Iinc/ #-ldl NAME = libplugin.so SRCFILES = $(wildcard $(SRCDIR)*.cpp) @@ -12,7 +12,7 @@ OBJFILES = $(patsubst $(SRCDIR)%, $(BUILDDIR)%, $(patsubst %.cpp,%.so,$(SRCFILES all: createhfiles $(BUILDDIR)$(NAME) $(BUILDDIR)%.so: $(SRCDIR)%.cpp $(BUILDDIR) - $(CXX) -fPIC -shared $(CFLAGS) $(SRCDIR)$*.cpp $(LDFLAGS) -o $@ + $(CXX) -fPIC -shared $(CFLAGS) $(SRCDIR)*.cpp -o $@ $(LDFLAGS) $(BUILDDIR)%: $(SRCDIR)%.cpp $(BUILDDIR) $(CXX) $(CFLAGS) $(SRCDIR)$*.cpp -o $@ diff --git a/inc/cppplugin.h b/inc/cppplugin.h deleted file mode 100644 index 6088c42..0000000 --- a/inc/cppplugin.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -class CppPlugin { -public: - virtual void onLoad() = 0; - virtual void onEnable() = 0; - virtual void onDisable() = 0; -}; - - -typedef CppPlugin* (*initfptr)(); diff --git a/inc/libplugin.h b/inc/libplugin.h new file mode 100644 index 0000000..972ff21 --- /dev/null +++ b/inc/libplugin.h @@ -0,0 +1,23 @@ +#pragma once +#include + +#include +#include + +#include "plugin.h" + +//extern "C" { + +jclass CPPPLUGINCLASS; +jclass EVENTCLASS; +jclass MAPCLASS; +jclass LISTENERCLASS; +jfieldID EVENTDATAF; +jfieldID EVENTNAMEF; +jmethodID MAPGET; +jmethodID MAPPUT; +jmethodID LISTENERCONTR; + +CppPlugin* plugin; //what happens, with more than one plugin? + +//} //extern "C" \ No newline at end of file diff --git a/inc/plugin.h b/inc/plugin.h new file mode 100644 index 0000000..cedbe8c --- /dev/null +++ b/inc/plugin.h @@ -0,0 +1,37 @@ +#pragma once +#include + +#include +#include + +class CppPlugin { +public: + void* handle; + virtual void onLoad() = 0; + virtual void onEnable() = 0; + virtual void onDisable() = 0; + //virtual ~CppPlugin(); +}; + +class Event { +private: + std::string name; //name of the event + jobject input; //original Event object (type CppEvent) + std::map data; +public: + jobject getMap(JNIEnv* env); + const std::string& getName(); + void* getData(JNIEnv* env, const std::string& name); + void setData(const std::string& name, void* data); + + void reapply(JNIEnv* env, jobject jevent); + + Event(JNIEnv* env, jobject jevent); + //virtual ~Event(); +}; + +//function pointer +typedef void (*eventfptr)(CppPlugin*, Event*); +typedef std::map (*getEventsfptr)(); +typedef CppPlugin* (*initfptr)(); + diff --git a/runall.sh b/runall.sh index c2c109f..f66c6de 100755 --- a/runall.sh +++ b/runall.sh @@ -1,5 +1,6 @@ #!/bin/bash mvn package +rm target/*.so make -j1 all #that makefile is not paralllizable mkdir -p testserver/plugins/CppPlugins cp target/Cppplugin-0.1-SNAPSHOT-final.jar testserver/plugins/ diff --git a/src/main/cpp/src/libplugin.cpp b/src/main/cpp/src/libplugin.cpp index 143cf0d..96b2c0c 100644 --- a/src/main/cpp/src/libplugin.cpp +++ b/src/main/cpp/src/libplugin.cpp @@ -4,32 +4,28 @@ #include #include //dynamic linking -#include "cppplugin.h" //plugin definitions +#include -//jfieldID DATAFIELDID = 0; -jclass CPPPLUGINCLASS = 0; -CppPlugin* plugin = 0; - -/* -void setData(CppPlugin* d, JNIEnv* env, jobject thisobj) { - std::cout << "set data: " << DATAFIELDID << std::endl; - env->SetLongField(thisobj, DATAFIELDID, reinterpret_cast(d)); -} - -CppPlugin* getData(JNIEnv* env, jobject thisobj) { - std::cout << "get data: " << DATAFIELDID << std::endl; - return reinterpret_cast(env->GetLongField(thisobj, DATAFIELDID)); -}*/ JNIEXPORT jboolean JNICALL Java_de_mrbesen_cppplugins_CppPlugin_init_1(JNIEnv* env, jobject thisobj) { - std::cout << "init!! aus cpp!!!" << std::endl; + std::cout << "init libplugin loading java references, 1 = good, 0 = bad" << std::endl; CPPPLUGINCLASS = env->FindClass("de/mrbesen/cppplugins/CppPlugin"); - std::cout << "findclass: " << (!CPPPLUGINCLASS) << std::endl; - //DATAFIELDID = env->GetFieldID(CPPPLUGINCLASS, "data", "J"); - //std::cout << "findfield " << (!DATAFIELDID) << std::endl; + EVENTCLASS = env->FindClass("de/mrbesen/cppplugins/CppEvent"); + MAPCLASS = env->FindClass("java/util/Map"); + LISTENERCLASS = env->FindClass("de/mrbesen/cppplugins/CppPlugin$CppListener"); + std::cout << "find classes: " << (!!CPPPLUGINCLASS) << (!!EVENTCLASS) << (!!MAPCLASS) << (!!LISTENERCLASS) << std::endl; - return true; + EVENTDATAF = env->GetFieldID(EVENTCLASS, "data", "Ljava/util/Map;"); + EVENTNAMEF = env->GetFieldID(EVENTCLASS, "name", "Ljava/lang/String;"); + std::cout << "findfields: " << (!!EVENTDATAF) << (!!EVENTNAMEF) << std::endl; + + MAPGET = env->GetMethodID(MAPCLASS, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); + MAPPUT = env->GetMethodID(MAPCLASS, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + LISTENERCONTR = env->GetMethodID(LISTENERCLASS, "", "(Ljava/lang/String;J)V"); + std::cout << "find methods: " << (!!MAPGET) << (!!MAPPUT) << (!!LISTENERCONTR) << std::endl; + + return ((!CPPPLUGINCLASS) + (!EVENTCLASS) + (!MAPCLASS) + (!EVENTDATAF) + (!EVENTNAMEF) + (!MAPGET) + (!MAPPUT) + (!LISTENERCONTR)) == 0; //one nullptr -> inverted to 1 -> ends up at end -> false } @@ -44,24 +40,27 @@ JNIEXPORT jboolean JNICALL Java_de_mrbesen_cppplugins_CppPlugin_loadPlugin(JNIEn //open plugin std::cout << "open plugin " << cpath << std::endl; void* handle = dlopen(cpath, RTLD_LAZY); - if (!handle) + if (!handle) { + std::cout << "could not create handle of: " << cpath << " error: " << dlerror() << std::endl; return false; + } //throw std::string("Error: plugin could not be opend. ") + dlerror(); //load function pointer initfptr initf = (initfptr) dlsym(handle, "init"); if(!initf) { - std::cout << "Could not find function init" << std::endl; + std::cout << "Could not find function init: " << dlerror() << std::endl; dlclose(handle); return false; - } + } plugin = initf(); + plugin->handle = handle; //store data //setData(data, env, thisobj); - - return true; + std::cout << "plugin: " << (bool)plugin << std::endl; + return (bool) plugin; // converted to boolean here } /* @@ -95,6 +94,7 @@ JNIEXPORT void JNICALL Java_de_mrbesen_cppplugins_CppPlugin_onDisable_1(JNIEnv* //TODO std::cout << "lib::onDisable()" << std::endl; plugin->onDisable(); + dlclose(plugin->handle); } /* @@ -102,9 +102,26 @@ JNIEXPORT void JNICALL Java_de_mrbesen_cppplugins_CppPlugin_onDisable_1(JNIEnv* * Method: fireEvent * Signature: (Lde/mrbesen/cppplugins/CppEvent;I)Lde/mrbesen/cppplugins/CppEvent; */ -JNIEXPORT jobject JNICALL Java_de_mrbesen_cppplugins_CppPlugin_fireEvent(JNIEnv* env, jobject thisobj, jobject event, jint functionid) { - //TODO - return event; +JNIEXPORT jobject JNICALL Java_de_mrbesen_cppplugins_CppPlugin_fireEvent(JNIEnv* env, jobject thisobj, jobject jevent, jlong functionid) { + std::cout << "lib::fireEvent()" << std::endl; + if(functionid == 0) { + std::cout << "invalid function id" << std::endl; + return jevent; + } + + //cast function + eventfptr f = reinterpret_cast(functionid); + + //cast event + Event event(env, jevent); + + //call it + f(plugin, &event); + + //put changed fields back in the jevent + event.reapply(env, jevent); + + return jevent; } /* @@ -123,7 +140,90 @@ JNIEXPORT jboolean JNICALL Java_de_mrbesen_cppplugins_CppPlugin_onCmd(JNIEnv* en * Signature: ()[Lde/mrbesen/cppplugins/CppPlugin/CppListener; */ JNIEXPORT jobjectArray JNICALL Java_de_mrbesen_cppplugins_CppPlugin_getListener(JNIEnv* env, jobject thisobj) { + //call getEvents + std::map events; + getEventsfptr getEventsf = (getEventsfptr) dlsym(plugin->handle, "getEvents"); + if(getEventsf) { + //only non null + events = getEventsf(); + } + + //create array jclass clas = env->FindClass("de/mrbesen/cppplugins/CppPlugin/CppListener"); - jobjectArray arr = env->NewObjectArray(0, clas, 0); + jobjectArray arr = env->NewObjectArray(events.size(), clas, 0); + + //populate array + int i = 0; + for(auto it : events) { + //create object + jstring eventname = env->NewStringUTF(it.first.c_str()); + jobject listener = env->NewObject(LISTENERCLASS, LISTENERCONTR, eventname, it.second); + env->DeleteLocalRef(eventname); + + //set array + env->SetObjectArrayElement(arr, i++, listener); + } + return arr; } + + + + +///////// EVENTS + +jobject Event::getMap(JNIEnv* env) { + return env->GetObjectField(input, EVENTDATAF); +} + +const std::string& Event::getName() { + return name; +} + +void* Event::getData(JNIEnv* env, const std::string& name) { + std::cout << "Try to access " << name << std::endl; + //search in map + auto it = data.find(name); + if(it == data.end()) { + //search in original object + //construct string + jstring term = env->NewStringUTF(name.c_str()); + + //call data.get() + jobject map = getMap(env); + jobject content = env->CallObjectMethod(map, MAPGET, term); + + //data.insert for next time + data.insert({name, content}); + + //delete string + env->DeleteLocalRef(term); + } else { + return it->second; + } + + return nullptr; +} + +void Event::setData(const std::string& name, void* d) { + //just put it in the map + data.insert({name, d}); +} + +void Event::reapply(JNIEnv* env, jobject jevent) { + jobject map = getMap(env); + for(auto it : data) { + std::cout << "write back to java: " << it.first << std::endl; + jstring key = env->NewStringUTF(it.first.c_str()); + + env->CallObjectMethod(map, MAPPUT, key, it.second); + env->DeleteLocalRef(key); + } +} + +Event::Event(JNIEnv* env, jobject jevent) { + //get name + jstring name = (jstring) env->GetObjectField(jevent, EVENTNAMEF); + this->name = std::string(env->GetStringUTFChars(name, 0)); + input = jevent; +} \ No newline at end of file diff --git a/src/main/java/de/mrbesen/cppplugins/CppLoader.java b/src/main/java/de/mrbesen/cppplugins/CppLoader.java index 30f3570..078a6ee 100644 --- a/src/main/java/de/mrbesen/cppplugins/CppLoader.java +++ b/src/main/java/de/mrbesen/cppplugins/CppLoader.java @@ -100,7 +100,7 @@ public class CppLoader implements PluginLoader { private class AdapterExecutor implements EventExecutor { CppPlugin plugin; - int functionid; + long functionid; @Override public void execute(Listener listener, Event event) throws EventException { diff --git a/src/main/java/de/mrbesen/cppplugins/CppPlugin.java b/src/main/java/de/mrbesen/cppplugins/CppPlugin.java index 296b1b8..073954e 100644 --- a/src/main/java/de/mrbesen/cppplugins/CppPlugin.java +++ b/src/main/java/de/mrbesen/cppplugins/CppPlugin.java @@ -1,6 +1,7 @@ package de.mrbesen.cppplugins; import com.avaje.ebean.EbeanServer; +import lombok.AllArgsConstructor; import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.Server; @@ -35,7 +36,7 @@ public class CppPlugin implements Plugin { public native void onLoad(); public native void onEnable_(); public native void onDisable_(); - protected native CppEvent fireEvent(CppEvent e, int functionid); + protected native CppEvent fireEvent(CppEvent e, long functionid); protected native boolean onCmd(CommandSender sender, Command cmd, String label, String[] args); native CppListener[] getListener(); @@ -165,8 +166,9 @@ public class CppPlugin implements Plugin { return null; } - public class CppListener implements Listener { + @AllArgsConstructor + static class CppListener implements Listener { String eventfilter; - int functionid; + long functionid; } } diff --git a/src/main/java/de/mrbesen/cppplugins/CppPlugins.java b/src/main/java/de/mrbesen/cppplugins/CppPlugins.java index b976258..a4d29f4 100644 --- a/src/main/java/de/mrbesen/cppplugins/CppPlugins.java +++ b/src/main/java/de/mrbesen/cppplugins/CppPlugins.java @@ -2,12 +2,11 @@ package de.mrbesen.cppplugins; import lombok.Getter; import org.bukkit.Bukkit; -import org.bukkit.plugin.InvalidDescriptionException; -import org.bukkit.plugin.InvalidPluginException; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; import java.io.File; +import java.util.logging.Level; public class CppPlugins extends JavaPlugin { @@ -28,8 +27,8 @@ public class CppPlugins extends JavaPlugin { System.out.println("loaded verysimpleplugin.so"); //TODO: trigger onLoad in those Plugins - } catch (InvalidDescriptionException | InvalidPluginException e) { - e.printStackTrace(); + } catch (Throwable e) { + getLogger().log(Level.SEVERE, "Error ocoured during loading verysimpleplugin.so", e); } } diff --git a/testplugins/verysimpleplugin/Makefile b/testplugins/verysimpleplugin/Makefile index 1657aeb..a11dcbb 100644 --- a/testplugins/verysimpleplugin/Makefile +++ b/testplugins/verysimpleplugin/Makefile @@ -1,9 +1,9 @@ -CFLAGS = -Wall -O2 -pedantic-errors -std=c++17 -g +CFLAGS = -Wall -pedantic-errors -std=c++17 -g SRCDIR = src/ INCDIR = ../../inc -LDFLAGS = -I/usr/lib/jvm/java-8-openjdk-amd64/include/ -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux/ -I$(INCDIR) +LDFLAGS = -I/usr/lib/jvm/java-8-openjdk-amd64/include/ -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux/ -I$(INCDIR) -I../../src/main/cpp/inc NAME = verysimpleplugin.so all: - g++ -fPIC -shared $(CFLAGS) $(SRCDIR)*.cpp $(LDFLAGS) -o $(NAME) + g++ -fPIC -shared $(CFLAGS) $(SRCDIR)*.cpp $(LDFLAGS) ../../src/main/cpp/src/libplugin.cpp -o $(NAME) diff --git a/testplugins/verysimpleplugin/src/plugin.cpp b/testplugins/verysimpleplugin/src/plugin.cpp index 2ef1d5d..e0ff547 100644 --- a/testplugins/verysimpleplugin/src/plugin.cpp +++ b/testplugins/verysimpleplugin/src/plugin.cpp @@ -1,8 +1,8 @@ -#include "cppplugin.h" +#include "plugin.h" #include -extern "C" { +extern "C" { class MyPlugin : public CppPlugin { public: @@ -28,4 +28,8 @@ CppPlugin* init() { return new MyPlugin(); } +void eventJoin(CppPlugin* pl, Event* e) { + std::cout << "join " << e->getName() << std::endl; +} + }//extern "C" \ No newline at end of file