Skip to content

Commit

Permalink
JNAerator + BridJ: prepare C++ namespaces (issue #446), extend `@Name…
Browse files Browse the repository at this point in the history
…` to all entities (issue #443), fix Pointer signature matching (way stricter now)
  • Loading branch information
ochafik committed Sep 22, 2013
1 parent edf0918 commit 5bd6403
Show file tree
Hide file tree
Showing 14 changed files with 190 additions and 51 deletions.
12 changes: 1 addition & 11 deletions libraries/BridJ/RebuildNative
@@ -1,14 +1,4 @@
#!/bin/bash

./BuildNative clean
FAST=1 ./BuildNative clean
./BuildNative

if [[ -d /Applications ]] ; then
# MacOS X
for T in ios android ; do
TARGET=$T ./BuildNative clean
TARGET=$T ./BuildNative fast ;
done ;
fi


2 changes: 1 addition & 1 deletion libraries/BridJ/src/main/java/org/bridj/CRuntime.java
Expand Up @@ -581,7 +581,7 @@ public long sizeOf(Type structType, StructIO io) {
}
protected Set<Class> rootCallbackClasses = new HashSet<Class>(Arrays.asList(Callback.class, DynamicFunction.class));

protected Method getUniqueAbstractCallbackMethod(Class type) {
public Method getUniqueAbstractCallbackMethod(Class type) {
Class<?> parent = null;
while ((parent = type.getSuperclass()) != null && !rootCallbackClasses.contains(parent)) {
type = parent;
Expand Down
3 changes: 1 addition & 2 deletions libraries/BridJ/src/main/java/org/bridj/ann/Name.java
Expand Up @@ -36,7 +36,7 @@
import java.lang.annotation.Target;

/**
* Specify the real non-obfuscated name of a field / method (useful when the
* Specify the real non-obfuscated name of a field / method / class (useful when the
* name is a Java keyword but not a C one, e.g. to bind a C function named
* 'transient')
*
Expand All @@ -45,6 +45,5 @@
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Name {

String value();
}
47 changes: 47 additions & 0 deletions libraries/BridJ/src/main/java/org/bridj/ann/Namespace.java
@@ -0,0 +1,47 @@
/*
* BridJ - Dynamic and blazing-fast native interop for Java.
* http://bridj.googlecode.com/
*
* Copyright (c) 2010-2013, Olivier Chafik (http://ochafik.com/)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Olivier Chafik nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.bridj.ann;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Specify the real non-obfuscated namespace of a C++ class.
*
* @author Olivier Chafik
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Namespace {
String value();
}
4 changes: 3 additions & 1 deletion libraries/BridJ/src/main/java/org/bridj/cpp/CPPRuntime.java
Expand Up @@ -82,6 +82,7 @@
import org.bridj.demangling.Demangler.SpecialName;
import static org.bridj.Pointer.*;
import org.bridj.StructObject;
import org.bridj.ann.Name;
import org.bridj.demangling.Demangler;

/**
Expand Down Expand Up @@ -496,7 +497,8 @@ int getPositionInVirtualTable(Method method, NativeLibrary library) {
}

String getCPPClassName(Class<?> declaringClass) {
return declaringClass.getSimpleName();
Name name = declaringClass.getAnnotation(Name.class);
return name == null ? declaringClass.getSimpleName() : name.value();
}

public int getPositionInVirtualTable(Pointer<Pointer<?>> pVirtualTable, Method method, NativeLibrary library) {
Expand Down
101 changes: 87 additions & 14 deletions libraries/BridJ/src/main/java/org/bridj/demangling/Demangler.java
Expand Up @@ -35,6 +35,7 @@
import java.lang.reflect.*;
import java.lang.annotation.*;
import java.util.Arrays;
import java.util.regex.Pattern;
import org.bridj.AbstractBridJRuntime;
import org.bridj.BridJ;
import org.bridj.CRuntime;
Expand All @@ -48,11 +49,13 @@
import org.bridj.TimeT;
import org.bridj.SizeT;
import org.bridj.CLong;
import org.bridj.Callback;
import org.bridj.ValuedEnum;
import org.bridj.ann.Constructor;
import org.bridj.ann.Ptr;
import org.bridj.ann.Convention;
import org.bridj.ann.Name;
import org.bridj.ann.Namespace;
import org.bridj.ann.Template;
import org.bridj.util.AnnotationUtils;
import static org.bridj.util.AnnotationUtils.*;
Expand Down Expand Up @@ -282,12 +285,15 @@ public interface TemplateArg {
}

public static String getMethodName(Method method) {
Name nameAnn = method.getAnnotation(Name.class);
if (nameAnn != null) {
return nameAnn.value();
}
Name name = method.getAnnotation(Name.class);
return name == null ? method.getName() : name.value();
}

return method.getName();
public static String getClassName(Type type) {
assert type != null;
Class<?> typeClass = Utils.getClass(type);//getTypeClass(type);
Name name = typeClass.getAnnotation(Name.class);
return name == null ? typeClass.getSimpleName() : name.value();
}

public static class Symbol {
Expand Down Expand Up @@ -424,7 +430,7 @@ public boolean matchesVirtualTable(Class<?> type) {
}

public boolean matchesConstructor(Type type, java.lang.reflect.Constructor<?> constr) {
if (!symbol.contains(Utils.getClass(type).getSimpleName())) {
if (!symbol.contains(getClassName(type))) {
return false;
}

Expand Down Expand Up @@ -467,15 +473,39 @@ public static abstract class TypeRef implements TemplateArg {

public abstract StringBuilder getQualifiedName(StringBuilder b, boolean generic);

public String getQualifiedName(boolean generic) {
StringBuilder sb = getQualifiedName(new StringBuilder(), generic);
return sb == null ? null : sb.toString();
}

public boolean matchesParam(Object param, Annotations annotations) {
return (param instanceof Type) && matches((Type) param, annotations);
}

public boolean matches(Type type, Annotations annotations) {
String thisName = getQualifiedName(new StringBuilder(), false).toString();
Class typeClass = getTypeClass(type);
String typeName = typeClass.getSimpleName();
return thisName.equals(typeName) || thisName.equals(typeClass.getName());
String thisName = getQualifiedName(false);
if (thisName == null)
return false;
Class<?> typeClass = getTypeClass(type);
String name = getClassName(typeClass);
if (thisName.equals(name))
return true;
Namespace ns = typeClass.getAnnotation(Namespace.class);
String pack;
if (ns == null) {
if (typeClass.getPackage() == null)
pack = "";
else
pack = typeClass.getPackage().getName();
} else {
pack = ns.value().replaceAll("\b::\b", ".").trim();
}
if (pack.length() == 0)
return false;
String qname = pack + "." + name;
if (thisName.matches("\b" + Pattern.quote(qname)))
return true;
return false;
}

@Override
Expand Down Expand Up @@ -525,6 +555,7 @@ public static class PointerTypeRef extends TypeRef {
public TypeRef pointedType;

public PointerTypeRef(TypeRef pointedType) {
assert pointedType != null;
this.pointedType = pointedType;
}

Expand All @@ -549,7 +580,13 @@ public boolean matches(Type type, Annotations annotations) {
Class typeClass = getTypeClass(type);
if (!Pointer.class.isAssignableFrom(typeClass))
return false;
Type pointedType = Utils.getUniqueParameterizedTypeParameter(type);
// return true;
Type pointedType = normalize(Utils.getUniqueParameterizedTypeParameter(type));
if (this.pointedType == null || this.pointedType.toString().equals("void"))
return pointedType == null;
if (pointedType == null) {
return true;
}
return this.pointedType.matches(pointedType, annotations);
}

Expand Down Expand Up @@ -607,11 +644,33 @@ static Class<?> getTypeClass(Type type) {
return Object[].class;
}
}
throw new UnsupportedOperationException("Unknown type type : " + type.getClass().getName());
return null;
// throw new UnsupportedOperationException("Unknown type type : " + (type == null ? null : type.getClass().getName()));
}

private static Type normalize(Type t) {
if (t instanceof WildcardType) {
WildcardType wt = (WildcardType) t;
if (wt.getLowerBounds().length == 1)
return normalize(wt.getLowerBounds()[0]);
return null;
}
Class<?> c = Utils.getClass(t);
if (c != null && c.isPrimitive()) {
if (t == float.class) return Float.class;
if (t == double.class) return Double.class;
if (t == byte.class) return Byte.class;
if (t == char.class) return Character.class;
if (t == short.class) return Short.class;
if (t == int.class) return Integer.class;
if (t == long.class) return Long.class;
if (t == boolean.class) return Boolean.class;
if (t == void.class) return Void.class;
}
return t;
}
static boolean equivalentTypes(Type a, Class ac, Annotations aAnnotations, Type b, Class bc, Annotations bAnnotations) {
if (a.equals(b)) {
if (normalize(a).equals(normalize(b))) {
return true;
}

Expand Down Expand Up @@ -679,6 +738,8 @@ public StringBuilder getQualifiedName(StringBuilder b, boolean generic) {
public boolean matches(Type type, Annotations annotations) {
Class<?> tc = getTypeClass(this.type);
Class<?> typec = getTypeClass(type);
if (typec == null)
return true; // TODO check
if (tc == typec || tc.equals(typec)) {
return true;
}
Expand Down Expand Up @@ -805,7 +866,8 @@ public TypeRef getEnclosingType() {

@Override
public boolean matches(Type type, Annotations annotations) {
if (getTypeClass(type).getSimpleName().equals(ident.simpleName)) {
Class<?> typeClass = getTypeClass(type);
if (typeClass != null && typeClass.getSimpleName().equals(ident.simpleName)) {
return true;
}

Expand Down Expand Up @@ -859,6 +921,17 @@ public StringBuilder getQualifiedName(StringBuilder b, boolean generic) {
return null;
}

@Override
public boolean matches(Type type, Annotations annotations) {
Class<?> typeClass = getTypeClass(type);
if (!Callback.class.isAssignableFrom(typeClass))
return false;
Method method = CRuntime.getInstance().getUniqueAbstractCallbackMethod(typeClass);
if (method == null)
return false;
return function.matches(method);
}

@Override
public String toString() {
return function.toString();
Expand Down
3 changes: 2 additions & 1 deletion libraries/BridJ/src/test/cpp/test/Makefile
Expand Up @@ -6,14 +6,15 @@ SHARED_LIB = test
UNITS += test
UNITS += structs
UNITS += templates
UNITS += objctest

CPPFLAGS += -fPIC

ifeq ($(OS), darwin)
UNITS += objctest
CPPFLAGS += -I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/
#LDFLAGS += -lobjc
LDFLAGS += -framework Foundation
LDFLAGS += -framework Foundation -all_load
LDFLAGS += -install_name @rpath/libtest.dylib
endif

Expand Down
3 changes: 3 additions & 0 deletions libraries/BridJ/src/test/cpp/test/objctest.m
@@ -1,3 +1,5 @@
#if defined(__APPLE__) || defined(__Darwin__)

#include "objctest.h"

@implementation DelgHolder
Expand All @@ -23,3 +25,4 @@ int forwardBlockCallIntIntInt(int (^block)(int, int), int a, int b)
return block(a, b);
}

#endif // defined(__APPLE__) || defined(__Darwin__)
8 changes: 4 additions & 4 deletions libraries/BridJ/src/test/java/org/bridj/CallbackTest.java
Expand Up @@ -100,11 +100,11 @@ public Pointer doSomething(Pointer a, Pointer b) {

assertEquals(4, forwardPtrCall(new MyPtrCallback() {
@Override
public Pointer<Integer> doSomething(Pointer<Integer> a, Pointer<Integer> b) {
return pointerToInt(a.get() + b.get() + 1);
public Pointer<?> doSomething(Pointer<?> a, Pointer<?> b) {
return pointerToInt(a.as(int.class).get() + b.as(int.class).get() + 1);
//return pointerToInt(a.getInt() + b.getInt() + 1);
}
}.toPointer(), pa, pb).getInt()); // .get());
}.toPointer(), pa, pb).as(int.class).getInt()); // .get());
}

@Test
Expand All @@ -116,7 +116,7 @@ public void testNativeTargetPtrCallbacks() {
static native Pointer<MyPtrCallback> getPtrAdder();

public static abstract class MyPtrCallback extends Callback {
public abstract Pointer<Integer> doSomething(Pointer<Integer> a, Pointer<Integer> b);
public abstract Pointer<?> doSomething(Pointer<?> a, Pointer<?> b);
}


Expand Down
Expand Up @@ -47,7 +47,6 @@ This file is part of JNAerator (http://jnaerator.googlecode.com/).
public abstract class Element {
//List<Element> parentElements = new ArrayList<Element>();
Element parentElement;
protected List<String> nameSpace = new ArrayList<String>();
String elementFile;
int elementLine = -1;
String commentBefore, commentAfter;
Expand Down Expand Up @@ -114,17 +113,6 @@ public void stripDetails() {
setElementFile(null);
setElementLine(-1);
}
public void addNameSpace(String nameSpace) {
this.nameSpace.add(0, nameSpace);
}
public List<String> getNameSpace() {
return unmodifiableList(nameSpace);
}
public void setNameSpace(List<String> nameSpace) {
this.nameSpace.clear();
this.nameSpace.addAll(nameSpace);
}

public Element importComments(Element e, String... extraComments) {
if (e != null) {
importDetails(e, false);
Expand All @@ -137,10 +125,7 @@ public Element importComments(Element e, String... extraComments) {
public Element importDetails(Element from, boolean move) {
if (from == null)
return this;

if (!from.getNameSpace().isEmpty())
setNameSpace(from.getNameSpace());


if (from.getElementFile() != null)
setElementFile(from.getElementFile());
if (from.getElementLine() >= 0)
Expand Down
Expand Up @@ -170,6 +170,8 @@ protected void visitCPPClass(Struct struct) {

protected void doVisitStruct(Struct struct) {
visitTaggedTypeRef(struct);
if (struct.getParentNamespace() != null)
visitIdentifier(struct.getParentNamespace());
visit(struct.getDeclarations());
visit(struct.getProtocols());
visit(struct.getParents());
Expand Down

0 comments on commit 5bd6403

Please sign in to comment.