Skip to content

Commit

Permalink
WIP generate class
Browse files Browse the repository at this point in the history
  • Loading branch information
xpenatan committed Jul 4, 2023
1 parent bbb2cd1 commit 96f7855
Show file tree
Hide file tree
Showing 7 changed files with 274 additions and 45 deletions.
11 changes: 11 additions & 0 deletions example/example-build/jni/cpp/src/NormalClassTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "NormalClassTest.h"

int NormalClassTest::getIntValue()
{
return 0;
}

bool NormalClassTest::getBoolValue(float floatValue)
{
return true;
}
11 changes: 11 additions & 0 deletions example/example-build/jni/cpp/src/NormalClassTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef NORMALCLASSTEST_H
#define NORMALCLASSTEST_H

class NormalClassTest
{
public:
int getIntValue();
bool getBoolValue(float floatValue);
}

#endif //NORMALCLASSTEST_H
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,19 @@

import com.github.xpenatan.jparser.core.JParser;
import com.github.xpenatan.jparser.core.codeparser.IDLDefaultCodeParser;
import com.github.xpenatan.jparser.cpp.CppCodeParser;
import com.github.xpenatan.jparser.cpp.FileCopyHelper;
import com.github.xpenatan.jparser.idl.IDLReader;
import java.io.File;

public class Main {

public static void main(String[] args) throws Exception {
// generateClassOnly();
generateCPP();
}

private static void generateClassOnly() throws Exception {
String basePackage = "com.github.xpenatan.jparser.example";
String idlPath = "src\\main\\resources\\idl\\Test.idl";
String baseJavaDir = new File(".").getAbsolutePath() + "./example-base/src/main/java";
Expand All @@ -17,4 +24,21 @@ public static void main(String[] args) throws Exception {
IDLDefaultCodeParser idlParser = new IDLDefaultCodeParser(basePackage, "IDL-Test", idlReader);
JParser.generate(idlParser, baseJavaDir, genDir);
}

private static void generateCPP() throws Exception {
String basePackage = "com.github.xpenatan.jparser.example";
String idlPath = "src\\main\\resources\\idl\\Test.idl";
String baseJavaDir = new File(".").getAbsolutePath() + "./example-base/src/main/java";
String genDir = "../example-core/src/main/java";
String classPath = CppCodeParser.getClassPath("bullet-base", "gdx-1", "gdx-jnigen-loader", "jParser-loader");

String cppPath = new File("./jni/").getCanonicalPath();
String jniBuildPath = cppPath + "/build/c++/";
FileCopyHelper.copyDir(cppPath + "/cpp/src/", jniBuildPath + "/src");

IDLReader idlReader = IDLReader.readIDL(idlPath);
CppCodeParser idlParser = new CppCodeParser(basePackage, idlReader, classPath, jniBuildPath);
idlParser.generateClass = true;
JParser.generate(idlParser, baseJavaDir, genDir);
}
}
46 changes: 3 additions & 43 deletions example/example-build/src/main/resources/idl/Test.idl
Original file line number Diff line number Diff line change
@@ -1,49 +1,9 @@
[NoDelete]
interface NoDeleteClassTest {
[Value] static NormalClassTest GetNormalValueClass();
[Ref] ExtendClassTest getExtendClass(float floatParam, long intParam, [Const, Ref]NormalClassTest normalClass, float[] vertices);

static readonly attribute unsigned long ReadOnlyInt;
[Const]attribute NormalClassTest constNormalClass;
[Value]attribute NormalClassTest valueNormalClass;
attribute float floatAttribute;
attribute boolean boolAttribute;
attribute unsigned long flags;
attribute boolean [] arrayBoolean
attribute unsigned long[] arrayInt
attribute any anyObject;
};

[Prefix="MyPrefix::"]
interface PrefixClassTest {

};

[Prefix = "MyPrefix::", NoDelete]
interface PrefixNoDeleteClassTest {

};

[NoDelete, Prefix = "MyPrefix::"]
interface NoDeletePrefixClassTest {

};

[JSImplementation="NoDeletePrefixClassTest"]
interface ConcreteJSImplementationClassTest {
void ConcreteJSImplementationClassTest();
interface ParentClassTest {
float getFloatValue();
};

interface NormalClassTest {
long getIntValue();
boolean getBoolValue(float floatValue);
};

interface ExtendClassTest {
float getFloatValue();
}
ExtendClassTest implements NormalClassTest;

enum EnumTest {
"Test_Enum"
};
NormalClassTest implements ParentClassTest;
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.github.xpenatan.jparser.core.codeparser;

import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Modifier;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
Expand All @@ -10,28 +11,47 @@
import com.github.xpenatan.jparser.idl.IDLFile;
import com.github.xpenatan.jparser.idl.IDLReader;
import java.io.File;
import java.io.IOException;

/**
* @author xpenatan
*/
public abstract class IDLClassGeneratorParser extends DefaultCodeParser {

public boolean generateClass = false;

protected final IDLReader idlReader;
private String basePackage;

protected final CompilationUnit baseClassUnit;

private static String BASE_CLASS_NAME = "IDLBase";

public IDLClassGeneratorParser(String basePackage, String headerCMD, IDLReader idlReader) {
super(headerCMD);
this.basePackage = basePackage;
this.idlReader = idlReader;
try {
baseClassUnit = StaticJavaParser.parseResource("classes/" + BASE_CLASS_NAME + ".java");
} catch(IOException e) {
throw new RuntimeException(e);
}
}

@Override
public void onParseStart(JParser jParser) {
// Generate class if it does not exist
if(!generateClass) {
return;
}

// Generate class if it does not exist
String packagePath = File.separator + basePackage.replace(".", File.separator);
String basePath = new File(jParser.genDir + packagePath).getAbsolutePath();

String baseClassPath = basePath + File.separator + BASE_CLASS_NAME + ".java";
baseClassUnit.setPackageDeclaration(basePackage);
jParser.unitArray.add(new JParserItem(baseClassUnit, baseClassPath, baseClassPath));

for(IDLFile idlFile : idlReader.fileArray) {
for(IDLClass idlClass : idlFile.classArray) {
String className = idlClass.name;
Expand Down Expand Up @@ -63,4 +83,34 @@ private CompilationUnit setupClass(IDLClass idlClass) {

return compilationUnit;
}

@Override
public void onParseClassEnd(JParser jParser, CompilationUnit unit, ClassOrInterfaceDeclaration classOrInterfaceDeclaration) {
if(!generateClass) {
return;
}

String className = classOrInterfaceDeclaration.getName().toString();
IDLClass idlClass = idlReader.getClass(className);
if(idlClass != null) {
if(!idlClass.extendClass.isEmpty()) {
JParserItem parentItem = jParser.getParserUnitItem(idlClass.extendClass);
if(parentItem != null) {
CompilationUnit parentUnit = parentItem.unit;
if(parentUnit.getPackageDeclaration().isPresent()) {
String importName = parentUnit.getPackageDeclaration().get().getNameAsString() + "." + idlClass.extendClass;
unit.addImport(importName);
}
classOrInterfaceDeclaration.addExtendedType(idlClass.extendClass);
}
}
else {
if(baseClassUnit.getPackageDeclaration().isPresent()) {
String importName = baseClassUnit.getPackageDeclaration().get().getNameAsString() + "." + BASE_CLASS_NAME;
unit.addImport(importName);
}
classOrInterfaceDeclaration.addExtendedType(BASE_CLASS_NAME);
}
}
}
}
173 changes: 173 additions & 0 deletions jParser/core/src/main/resources/classes/IDLBase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
/**
* @author xpenatan
*/
public abstract class IDLBase {

public static boolean USE_REF_COUNTING = false;
public static boolean ENABLE_LOGGING = true;

protected long cPointer;
protected boolean cMemOwn;
private boolean disposed;
protected boolean destroyed;
private int refCount;

public IDLBase() {
}

protected void initObject(long cPtr, boolean cMemoryOwn) {
cMemOwn = cMemoryOwn;
cPointer = cPtr;
}

/**
* Set pointer if it's not owned by this object. Useful for setting temp objets
*/
public void setPointer(long cPtr) {
if(!cMemOwn) {
cPointer = cPtr;
}
}

/**
* Obtains a reference to this object, call release to free the reference.
*/
public void obtain() {
refCount++;
}

/**
* Release a previously obtained reference, causing the object to be disposed when this was the last reference.
*/
public void release() {
if(--refCount <= 0 && USE_REF_COUNTING) dispose();
}

/**
* @return Whether this instance is obtained using the {@link #obtain()} method.
*/
public boolean isObtained() {
return refCount > 0;
}

protected void construct() {
destroyed = false;
}

protected void reset(long cPtr, boolean cMemoryOwn) {
if(!destroyed) destroy();
cMemOwn = cMemoryOwn;
cPointer = cPtr;
construct();
}

@Override
public boolean equals(Object obj) {
return (obj instanceof IDLBase) && (((IDLBase)obj).cPointer == this.cPointer);
}

@Override
public int hashCode() {
return (int)cPointer;
}

/**
* @return The memory location (pointer) of this instance.
*/
public long getCPointer() {
return cPointer;
}

/**
* Take ownership of the native instance, causing the native object to be deleted when this object gets out of scope.
*/
public void takeOwnership() {
cMemOwn = true;
}

/**
* Release ownership of the native instance, causing the native object NOT to be deleted when this object gets out of
* scope.
*/
public void releaseOwnership() {
cMemOwn = false;
}

/**
* @return True if the native is destroyed when this object gets out of scope, false otherwise.
*/
public boolean hasOwnership() {
return cMemOwn;
}

/**
* Deletes the bullet object this class encapsulates. Do not call directly, instead use the {@link #dispose()} method.
*/
protected void deleteNative() {

}

public void dispose() {
if(refCount > 0 && USE_REF_COUNTING && ENABLE_LOGGING) {
error("Bullet", "Disposing " + toString() + " while it still has " + refCount + " references.");
}
if(cMemOwn) {
// Don't try to delete if this object did not create the pointer
disposed = true;
deleteNative();
cPointer = 0;
}
}

/**
* @return Whether the {@link #dispose()} method of this instance is called.
*/
public boolean isDisposed() {
return disposed;
}

@Override
public String toString() {
return getClass().getSimpleName() + "(" + cPointer + "," + cMemOwn + ")";
}

protected void destroy() {
try {
if(destroyed && ENABLE_LOGGING) {
error("Bullet", "Already destroyed " + toString());
}
destroyed = true;

if(cMemOwn && !disposed) {
if(ENABLE_LOGGING) {
error("Bullet", "Disposing " + toString() + " due to garbage collection.");
}
dispose();
}
} catch(Throwable e) {
error("Bullet", "Exception while destroying " + toString(), e);
}
}

@Override
protected void finalize() throws Throwable {
if(!destroyed && ENABLE_LOGGING) {
error("Bullet", "The " + getClass().getSimpleName() + " class does not override the finalize method.");
}
super.finalize();
}

/**
* Logs an error message to the console or logcat
*/
public static void error(String tag, String message) {
//TODO impl
}

/**
* Logs an error message to the console or logcat
*/
public static void error(String tag, String message, Throwable exception) {
//TODO impl
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ private void generateCppFile(ArrayList<JavaMethodParser.JavaSegment> javaSegment
CMethodParser.CMethod cMethod = findCMethod(javaMethod, cMethods);
if(cMethod == null)
throw new RuntimeException("Couldn't find C method for Java method '" + javaMethod.getClassName() + "#"
+ javaMethod.getName() + "'");
+ javaMethod.getName() + "'");
emitJavaMethod(buffer, javaMethod, cMethod);
}
}
Expand Down

0 comments on commit 96f7855

Please sign in to comment.