BridgeMethodCompiler extends BroMethodCompiler { protected static String createBridgeCWrapper(Type returnType, Type[] hiParameterTypes, Type[] loParameterTypes, String name) { if (hiParameterTypes.length != loParameterTypes.length) { if (hiParameterTypes.length < loParameterTypes.length) { throw new IllegalArgumentException("For va_arg functions lo's types parameter types must be a prefix of the hi type's parameters"); } if (!Arrays.asList(hiParameterTypes).subList(0, loParameterTypes.length).equals(Arrays.asList(loParameterTypes))) { throw new IllegalArgumentException("For va_arg functions lo's types parameter types must be a prefix of the hi type's parameters"); } } else { if (!Arrays.equals(hiParameterTypes, loParameterTypes)) { throw new IllegalArgumentException("hi and lo parameter types must be equal"); } } Map<String, String> typedefs = new TreeMap<String, String>(Collections.reverseOrder()); String hiReturnType = returnType instanceof StructureType ? "void" : getHiType(returnType); StringBuilder hiSignature = new StringBuilder(); hiSignature .append(hiReturnType) .append(' ') .append(name) .append("(void* target"); if (returnType instanceof StructureType) { hiSignature.append(", void* ret"); } StringBuilder loSignature = new StringBuilder(); String loReturnType = getLoType(returnType, name, 0, typedefs); loSignature .append(loReturnType) .append(' ') .append("(*)("); StringBuilder body = new StringBuilder(" {\n"); StringBuilder args = new StringBuilder(); for (int i = 0; i < hiParameterTypes.length; i++) { String arg = "p" + i; if (i > 0) { args.append(", "); } String hiParamType = getHiType(hiParameterTypes[i]); hiSignature.append(", "); hiSignature.append(hiParamType).append(' ').append(arg); if (i < loParameterTypes.length) { String loParamType = getLoType(hiParameterTypes[i], name, i + 1, typedefs); if (i > 0) { loSignature.append(", "); } loSignature.append(loParamType); if (hiParameterTypes[i] instanceof StructureType) { args.append("*((").append(loParamType).append("*)").append(arg).append(')'); } else { args.append(arg); } } else { args.append(arg); } } hiSignature.append(')'); if (loParameterTypes.length == 0) { loSignature.append("void"); } else if (loParameterTypes.length < hiParameterTypes.length) { loSignature.append(", ..."); } loSignature.append(')'); final String intend = " "; for (String typedef : typedefs.values()) { body.append(intend + typedef.replace("\n", "\n" + intend) + "\n"); } if (returnType instanceof StructureType) { body.append(" *((" + loReturnType + "*)ret) = ((" + loSignature + ") target)(" + args + ");\n"); } else if (returnType != Type.VOID) { body.append(" return ((" + loSignature + ") target)(" + args + ");\n"); } else { body.append(" ((" + loSignature + ") target)(" + args + ");\n"); } body.append("}\n"); return hiSignature.toString() + body.toString(); } BridgeMethodCompiler(Config config);   }
@Test public void testCreateBridgeCWrapperNoReturnNoParameters() { FunctionType functionType = new FunctionType(VOID); assertEquals( "void f(void* target) {\n" + " ((void (*)(void)) target)();\n" + "}\n", BridgeMethodCompiler.createBridgeCWrapper(functionType.getReturnType(), functionType.getParameterTypes(), functionType.getParameterTypes(), "f")); }
@Test public void testCreateBridgeCWrapperPrimitiveReturn() { FunctionType functionType = new FunctionType(I32); assertEquals( "int f(void* target) {\n" + " return ((int (*)(void)) target)();\n" + "}\n", BridgeMethodCompiler.createBridgeCWrapper(functionType.getReturnType(), functionType.getParameterTypes(), functionType.getParameterTypes(), "f")); }
@Test public void testCreateBridgeCWrapperPrimitiveParameters() { FunctionType functionType = new FunctionType(VOID, I8, I16, I32, I64, FLOAT, DOUBLE); assertEquals( "void f(void* target, char p0, short p1, int p2, long long p3, float p4, double p5) {\n" + " ((void (*)(char, short, int, long long, float, double)) target)(p0, p1, p2, p3, p4, p5);\n" + "}\n", BridgeMethodCompiler.createBridgeCWrapper(functionType.getReturnType(), functionType.getParameterTypes(), functionType.getParameterTypes(), "f")); }
@Test public void testCreateBridgeCWrapperPointerParameters() { FunctionType functionType = new FunctionType(VOID, I8_PTR, new PointerType(new StructureType(I32))); assertEquals( "void f(void* target, void* p0, void* p1) {\n" + " ((void (*)(void*, void*)) target)(p0, p1);\n" + "}\n", BridgeMethodCompiler.createBridgeCWrapper(functionType.getReturnType(), functionType.getParameterTypes(), functionType.getParameterTypes(), "f")); }
@Test public void testCreateBridgeCWrapperPointerReturn() { FunctionType functionType = new FunctionType(I8_PTR); assertEquals( "void* f(void* target) {\n" + " return ((void* (*)(void)) target)();\n" + "}\n", BridgeMethodCompiler.createBridgeCWrapper(functionType.getReturnType(), functionType.getParameterTypes(), functionType.getParameterTypes(), "f")); }
@Test public void testCreateBridgeCWrapperSmallStructByValParameter() { FunctionType functionType = new FunctionType(VOID, new StructureType(I32)); assertEquals( "void f(void* target, void* p0) {\n" + " typedef struct {int m0;} f_0001;\n" + " ((void (*)(f_0001)) target)(*((f_0001*)p0));\n" + "}\n", BridgeMethodCompiler.createBridgeCWrapper(functionType.getReturnType(), functionType.getParameterTypes(), functionType.getParameterTypes(), "f")); }
@Test public void testCreateBridgeCWrapperNestedStructByValParameter() { FunctionType functionType = new FunctionType(VOID, new StructureType( new StructureType(I32), new StructureType(I32))); assertEquals( "void f(void* target, void* p0) {\n" + " typedef struct {int m0;} f_0001_0001;\n" + " typedef struct {int m0;} f_0001_0000;\n" + " typedef struct {f_0001_0000 m0;f_0001_0001 m1;} f_0001;\n" + " ((void (*)(f_0001)) target)(*((f_0001*)p0));\n" + "}\n", BridgeMethodCompiler.createBridgeCWrapper(functionType.getReturnType(), functionType.getParameterTypes(), functionType.getParameterTypes(), "f")); }
@Test public void testCreateBridgeCWrapperComplexNestedStructByValParameter() { FunctionType functionType = new FunctionType(VOID, new StructureType( new StructureType(I8, I16), new StructureType(I32, I64), new StructureType(FLOAT, DOUBLE), new StructureType(I8_PTR, new PointerType(new StructureType(I32))))); assertEquals( "void f(void* target, void* p0) {\n" + " typedef struct {void* m0;void* m1;} f_0001_0003;\n" + " typedef struct {float m0;double m1;} f_0001_0002;\n" + " typedef struct {int m0;long long m1;} f_0001_0001;\n" + " typedef struct {char m0;short m1;} f_0001_0000;\n" + " typedef struct {f_0001_0000 m0;f_0001_0001 m1;f_0001_0002 m2;f_0001_0003 m3;} f_0001;\n" + " ((void (*)(f_0001)) target)(*((f_0001*)p0));\n" + "}\n", BridgeMethodCompiler.createBridgeCWrapper(functionType.getReturnType(), functionType.getParameterTypes(), functionType.getParameterTypes(), "f")); }
@Test public void testCreateBridgeCWrapperSmallStructByValReturn() { FunctionType functionType = new FunctionType(new StructureType(I32)); assertEquals( "void f(void* target, void* ret) {\n" + " typedef struct {int m0;} f_0000;\n" + " *((f_0000*)ret) = ((f_0000 (*)(void)) target)();\n" + "}\n", BridgeMethodCompiler.createBridgeCWrapper(functionType.getReturnType(), functionType.getParameterTypes(), functionType.getParameterTypes(), "f")); }
@Test public void testCreateBridgeCWrapperNestedStructByValReturn() { FunctionType functionType = new FunctionType(new StructureType(new StructureType(I32), new StructureType(I32))); assertEquals( "void f(void* target, void* ret) {\n" + " typedef struct {int m0;} f_0000_0001;\n" + " typedef struct {int m0;} f_0000_0000;\n" + " typedef struct {f_0000_0000 m0;f_0000_0001 m1;} f_0000;\n" + " *((f_0000*)ret) = ((f_0000 (*)(void)) target)();\n" + "}\n", BridgeMethodCompiler.createBridgeCWrapper(functionType.getReturnType(), functionType.getParameterTypes(), functionType.getParameterTypes(), "f")); }
@Test public void testCreateBridgeCWrapperComplexNestedStructByValReturnAndParameter() { StructureType structType = new StructureType( new StructureType(I8, I16), new StructureType(I32, I64), new StructureType(FLOAT, DOUBLE), new ArrayType(100, I32), new ArrayType(10, new StructureType(FLOAT, FLOAT)), new ArrayType(5, new ArrayType(10, I32)), new StructureType(I8_PTR, new PointerType(new StructureType(I32)))); FunctionType functionType = new FunctionType(structType, structType); assertEquals( "void f(void* target, void* ret, void* p0) {\n" + " typedef struct {void* m0;void* m1;} f_0001_0006;\n" + " typedef struct {float m0;float m1;} f_0001_0004;\n" + " typedef struct {float m0;double m1;} f_0001_0002;\n" + " typedef struct {int m0;long long m1;} f_0001_0001;\n" + " typedef struct {char m0;short m1;} f_0001_0000;\n" + " typedef struct {f_0001_0000 m0;f_0001_0001 m1;f_0001_0002 m2;int m3[100];f_0001_0004 m4[10];int m5[5][10];f_0001_0006 m6;} f_0001;\n" + " typedef struct {void* m0;void* m1;} f_0000_0006;\n" + " typedef struct {float m0;float m1;} f_0000_0004;\n" + " typedef struct {float m0;double m1;} f_0000_0002;\n" + " typedef struct {int m0;long long m1;} f_0000_0001;\n" + " typedef struct {char m0;short m1;} f_0000_0000;\n" + " typedef struct {f_0000_0000 m0;f_0000_0001 m1;f_0000_0002 m2;int m3[100];f_0000_0004 m4[10];int m5[5][10];f_0000_0006 m6;} f_0000;\n" + " *((f_0000*)ret) = ((f_0000 (*)(f_0001)) target)(*((f_0001*)p0));\n" + "}\n", BridgeMethodCompiler.createBridgeCWrapper(functionType.getReturnType(), functionType.getParameterTypes(), functionType.getParameterTypes(), "f")); }
@Test public void testCreateBridgeCWrapperVaArgs() { FunctionType hiType = new FunctionType(VOID, I8_PTR, I32, I32); FunctionType loType = new FunctionType(VOID, true, I8_PTR); assertEquals( "void f(void* target, void* p0, int p1, int p2) {\n" + " ((void (*)(void*, ...)) target)(p0, p1, p2);\n" + "}\n", BridgeMethodCompiler.createBridgeCWrapper(hiType.getReturnType(), hiType.getParameterTypes(), loType.getParameterTypes(), "f")); }
@Test public void testCreateBridgeCWrapperVectorStructByValReturn() { FunctionType functionType = new FunctionType(new VectorStructureType(0, Type.FLOAT, Type.FLOAT)); assertEquals( "void f(void* target, void* ret) {\n" + " typedef __attribute__((__ext_vector_type__(2))) float f_0000;\n" + " *((f_0000*)ret) = ((f_0000 (*)(void)) target)();\n" + "}\n", BridgeMethodCompiler.createBridgeCWrapper(functionType.getReturnType(), functionType.getParameterTypes(), functionType.getParameterTypes(), "f")); }
@Test public void testCreateBridgeCWrapperVectorArrayStructByValReturn() { FunctionType functionType = new FunctionType( new VectorStructureType(0, new VectorStructureType(0, Type.FLOAT, Type.FLOAT), new VectorStructureType(0, Type.FLOAT, Type.FLOAT))); assertEquals( "void f(void* target, void* ret) {\n" + " typedef __attribute__((__ext_vector_type__(2))) float f_0000_0000;\n" + " typedef struct { f_0000_0000 m[2];} f_0000;\n" + " *((f_0000*)ret) = ((f_0000 (*)(void)) target)();\n" + "}\n", BridgeMethodCompiler.createBridgeCWrapper(functionType.getReturnType(), functionType.getParameterTypes(), functionType.getParameterTypes(), "f")); }
@Test public void testCreateBridgeCWrapperPackedStructByVal() { FunctionType functionType = new FunctionType( VOID, new PackedStructureType(0, 0, 1, I32)); assertEquals( "void f(void* target, void* p0) {\n" + " #pragma pack(push, 1)\n" + " typedef struct {int m0;} f_0001;\n" + " #pragma pack(pop)\n" + " ((void (*)(f_0001)) target)(*((f_0001*)p0));\n" + "}\n", BridgeMethodCompiler.createBridgeCWrapper(functionType.getReturnType(), functionType.getParameterTypes(), functionType.getParameterTypes(), "f")); }