diff -u cxxwrap-20040103.orig/Arg.h cxxwrap-20040103/Arg.h --- cxxwrap-20040103.orig/Arg.h 2000-08-09 14:53:48.000000000 +0200 +++ cxxwrap-20040103/Arg.h 2005-01-07 15:30:49.343264000 +0100 @@ -43,6 +43,7 @@ Arg* clone(); int equals(Arg* other) { return type->equals(other->type); } + int equalsJava(Arg* other) { return type->equalsJava(other->type); } void print(); const char* name; diff -u cxxwrap-20040103.orig/ArrayCType.cxx cxxwrap-20040103/ArrayCType.cxx --- cxxwrap-20040103.orig/ArrayCType.cxx 2002-06-01 06:14:41.000000000 +0200 +++ cxxwrap-20040103/ArrayCType.cxx 2005-01-10 22:57:11.459278400 +0100 @@ -113,6 +113,7 @@ * pointers returned by GetArrayElements, the number of * calls to that function could be halved. */ + // why are these static? 20050109 larsa static int first = 1; static int depth = 1; static int obj = 0; @@ -138,16 +139,51 @@ // Is this a pointer to an array of objects? if (modifiers & M_POINTER && !strcmp(fbase->classname(),"ObjectCType")) obj_ptr = 1; + // FIXME: this flow path can be reshuffled / simplified since the + // if-else's are all the same. 20050109 larsa if (modifiers & M_POINTER && !obj_ptr) { + sprintf(buf+strlen(buf), "// 20050109 larsa\n"); + sprintf(buf+strlen(buf), "// FIXME: make sure indexing happens the right way here\n"); sprintf(buf+strlen(buf), - "int __TL%s = __env->GetArrayLength(%s);\n", + "const int __TL%s = __env->GetArrayLength(%s);\n", expr, expr ); +#if 0 + // sprintf(buf+strlen(buf), "// next line is illegal\n"); + // This line is not legal with MSVC since the array + // parameters are not all compile-time constants. sprintf(buf+strlen(buf), "%s%s __T%s[__TL%s][%d]", - fbase->BareCTypeName(), fbase->CTypeNameSuffix(), expr, expr, len + fbase->BareCTypeName(), fbase->CTypeNameSuffix(), + expr, expr, len ); +#else + sprintf(buf+strlen(buf), + "typedef %s%s __T%sTypeDef[%d]", + fbase->BareCTypeName(), fbase->CTypeNameSuffix(), + expr, len + ); + + CType* ct = base; + while (!strcmp(ct->classname(),"ArrayCType")) + { + ArrayCType* act = (ArrayCType*)ct; + sprintf(buf+strlen(buf), + "[%d]", + act->len + ); + ct = act->base; + } + + sprintf(buf+strlen(buf), ";\n"); + + sprintf(buf+strlen(buf), + "__T%sTypeDef * __T% +s", + expr, expr + ); +#endif } else { @@ -157,15 +193,27 @@ ); } - CType* ct = base; - while (!strcmp(ct->classname(),"ArrayCType")) + // 20050109 larsa - wrapped to not array typedef'ed pointer assigned + // by new-statement + if (!(modifiers & M_POINTER && !obj_ptr)) + { + CType* ct = base; + while (!strcmp(ct->classname(),"ArrayCType")) + { + ArrayCType* act = (ArrayCType*)ct; + sprintf(buf+strlen(buf), + "[%d]", + act->len + ); + ct = act->base; + } + } + + if (modifiers & M_POINTER && !obj_ptr) { - ArrayCType* act = (ArrayCType*)ct; sprintf(buf+strlen(buf), - "[%d]", - act->len - ); - ct = act->base; + " = new __T%sTypeDef[__TL%s]", + expr, expr); } sprintf(buf+strlen(buf), ";\n"); } @@ -316,15 +364,21 @@ { static int first = 1; static int depth = 1; + static int obj_ptr = 0; + static CType* fbase; /* Should be good for more dimensions than anybody would reasonably need */ char buf[CODE_BUFFER_SIZE*10] = ""; if (first) { + fbase = base; while (!strcmp(fbase->classname(),"ArrayCType")) fbase = ((ArrayCType*)fbase)->base; + // Is this a pointer to an array of objects? + if (modifiers & M_POINTER && !strcmp(fbase->classname(),"ObjectCType")) obj_ptr = 1; + if (modifiers & M_POINTER && modifiers & M_REFERENCE) { warning("Reference to pointer to array not supported"); @@ -379,6 +433,14 @@ "__env->Release%sArrayElements(%s, __element__%s, JNI_COMMIT);\n", fbase->JNIFunctionTypeName(), varname, expr ); + if (modifiers & M_POINTER && !obj_ptr) + { + + sprintf(buf+strlen(buf), + "// 20050109 larsa - free allocated array\n"); + sprintf(buf+strlen(buf), + "delete [] __T%s;\n", expr); + } } else { @@ -434,5 +496,11 @@ } } + if (first) + { + // Reset static variables + obj_ptr = 0; + } + return global.pool.add(buf); } Only in cxxwrap-20040103: ArrayCType.cxx~ diff -u cxxwrap-20040103.orig/CHANGELOG cxxwrap-20040103/CHANGELOG --- cxxwrap-20040103.orig/CHANGELOG 2004-01-03 23:15:08.000000000 +0100 +++ cxxwrap-20040103/CHANGELOG 2005-01-07 15:30:49.343264000 +0100 @@ -1,3 +1,12 @@ +20041216 Kristian Eide + - Option for automatic garbage collection of the native object when + the Java object is garbage collected (turnd on by the delOnGc() + method). + - Automatic GC is enabled by default for objects copied from the + stack to the heap by cxxwrap. + - Correctly wrap global operators. + - operator- (negate) is now called opNeg() (instead of opSub()). + 20040103 Dave Deaven - Fix memory error in TypeMap.h - make parser construct enum and method lists in proper order, diff -u cxxwrap-20040103.orig/CType.cxx cxxwrap-20040103/CType.cxx --- cxxwrap-20040103.orig/CType.cxx 2004-01-03 23:15:08.000000000 +0100 +++ cxxwrap-20040103/CType.cxx 2005-01-07 15:30:49.343264000 +0100 @@ -60,6 +60,12 @@ return 1; } +int CType::equalsJava(CType* other) +{ + if (strcmp(BareCTypeName(), other->BareCTypeName())) return 0; + return 1; +} + const char* CType::JNICast(const char* expr) { diff -u cxxwrap-20040103.orig/CType.h cxxwrap-20040103/CType.h --- cxxwrap-20040103.orig/CType.h 2004-01-03 23:15:08.000000000 +0100 +++ cxxwrap-20040103/CType.h 2005-01-07 15:30:49.353278400 +0100 @@ -58,6 +58,7 @@ virtual ~CType() { } virtual const char* classname() const { return "CType"; } virtual int equals(CType* other); + virtual int equalsJava(CType* other); // expand a templated type virtual CType* expand(Arg* parameters, Arg* args); diff -u cxxwrap-20040103.orig/Class.cxx cxxwrap-20040103/Class.cxx --- cxxwrap-20040103.orig/Class.cxx 2004-01-03 23:15:08.000000000 +0100 +++ cxxwrap-20040103/Class.cxx 2005-01-07 15:30:49.353278400 +0100 @@ -43,6 +43,7 @@ if (!strcmp(oct->name(), ect->getName())) { ect = (EnumCType*) ect->clone(); + ect->indirection_count = oct->indirection_count; ect->modifiers |= oct->modifiers; return ect; } @@ -100,6 +101,10 @@ * the new type. Also, insure that the final chased down * result is never marked as a TYPEDEF -- it isn't, anymore. */ + if (!strcmp(ctn, ct->BareCTypeName())) { + // Don't blow the stack on infinite recursion + return ct; + } ct = subst_typedef(ct, c, 1); ct->indirection_count += t->indirection_count; ct->modifiers |= t->modifiers; diff -u cxxwrap-20040103.orig/Emitter.cxx cxxwrap-20040103/Emitter.cxx --- cxxwrap-20040103.orig/Emitter.cxx 2001-06-26 06:58:29.000000000 +0200 +++ cxxwrap-20040103/Emitter.cxx 2005-01-07 15:39:11.525366400 +0100 @@ -118,7 +118,8 @@ make_path(buf); // have to ignore errors... } - sprintf(buf, "mkdir %s", path); + // msdos complains on existing directories + sprintf(buf, "if not exist %s\\*.* ( mkdir %s )", path, path); #else sprintf(buf, "mkdir -p %s", path); #endif diff -u cxxwrap-20040103.orig/EnumCType.cxx cxxwrap-20040103/EnumCType.cxx --- cxxwrap-20040103.orig/EnumCType.cxx 2001-06-09 07:03:40.000000000 +0200 +++ cxxwrap-20040103/EnumCType.cxx 2005-01-07 15:30:49.353278400 +0100 @@ -83,14 +83,14 @@ const char* EnumCType::JavaTypeName() { - if (indirection_count > 1) return NULL; + if (indirection_count > 1 || (indirection_count == 1 && (modifiers & CType::M_POINTER))) return NULL; return "int"; } const char* EnumCType::JNITypeName() { - if (indirection_count > 1) return NULL; + if (indirection_count > 1 || (indirection_count == 1 && (modifiers & CType::M_POINTER))) return NULL; return "jint"; } diff -u cxxwrap-20040103.orig/FunctionCType.cxx cxxwrap-20040103/FunctionCType.cxx --- cxxwrap-20040103.orig/FunctionCType.cxx 2002-06-01 06:14:42.000000000 +0200 +++ cxxwrap-20040103/FunctionCType.cxx 2005-01-07 15:30:49.353278400 +0100 @@ -80,7 +80,7 @@ FunctionCType::BareCTypeName() { char buf[TOKEN_BUFFER_SIZE]; - sprintf(buf, "%s (*)(", rtype->CTypeName()); + sprintf(buf, "%s (*%s)(", rtype->CTypeName(), arg_name != NULL ? arg_name : ""); Arg* a; for (a = args; a; a = a->next) @@ -92,6 +92,11 @@ return global.pool.add(buf); } +const char* +FunctionCType::CTypeNameSuffix() +{ + return ""; +} diff -u cxxwrap-20040103.orig/FunctionCType.h cxxwrap-20040103/FunctionCType.h --- cxxwrap-20040103.orig/FunctionCType.h 2002-05-15 12:01:03.000000000 +0200 +++ cxxwrap-20040103/FunctionCType.h 2005-01-07 15:30:49.363292800 +0100 @@ -28,10 +28,10 @@ class FunctionCType : public CType { public: FunctionCType(CType* rtype_, Arg* args_) : - CType(*rtype_), rtype(rtype_), args(args_), can_wrap(false) { } + CType(*rtype_), rtype(rtype_), args(args_), can_wrap(false), arg_name(NULL) { } FunctionCType(const FunctionCType& other) : CType(other), rtype(other.rtype->clone()), - args(other.args ? other.args->clone() : NULL), can_wrap(other.can_wrap) { } + args(other.args ? other.args->clone() : NULL), can_wrap(other.can_wrap), arg_name(other.arg_name) { } virtual CType* clone() { return new FunctionCType(*this); } virtual ~FunctionCType() { } virtual const char* classname() const { return "FunctionCType"; } @@ -40,6 +40,7 @@ const char* JNITypeName(); const char* JavaTypeName(); const char* BareCTypeName(); + const char* CTypeNameSuffix(); int writeTo(FILE* f); static FunctionCType* readFrom(FILE* f); @@ -47,10 +48,11 @@ CType* rtype; // return type Arg* args; // function arguments int can_wrap; // can we wrap this (requires a void* in arg list)? + const char* arg_name; private: FunctionCType(const CType& other) : - CType(other), rtype(NULL), args(NULL) { } + CType(other), rtype(NULL), args(NULL), arg_name(NULL) { } }; #endif // __FunctionCType__ diff -u cxxwrap-20040103.orig/JNIEmitter.cxx cxxwrap-20040103/JNIEmitter.cxx --- cxxwrap-20040103.orig/JNIEmitter.cxx 2004-01-03 23:15:08.000000000 +0100 +++ cxxwrap-20040103/JNIEmitter.cxx 2005-01-07 15:30:49.363292800 +0100 @@ -79,7 +79,7 @@ wrap_operators = arg_in("--jni-operators", argc - 1, argv + 1); emit_defaulted = arg_in("--jni-expand-defaults", argc - 1, argv + 1); - + const char* fn = argval_in("--jni-import-hook", argc - 1, argv + 1); if (fn) { @@ -351,11 +351,14 @@ char* s = (char*) strstr(a->default_value, "::"); if (s != NULL) { - *s = '\0'; - Class* c = jar->findClassByName(a->default_value); + char buf[TOKEN_BUFFER_SIZE]; + int end_idx = s - a->default_value; + strncpy(buf, a->default_value, end_idx); + buf[end_idx] = '\0'; + + Class* c = jar->findClassByName(buf); if (c) { - char buf[TOKEN_BUFFER_SIZE]; const char* dpn = c->dottedPackageName(); const char* opt_dot = *dpn == '\0' ? "" : "."; @@ -949,7 +952,7 @@ fprintf(fcxx, ", %s %s", jtna, a->name); } } - fprintf(fcxx, ")\n{\n%s* __obj = (%s*) __imp;\n", c->fullName(), c->fullName()); + fprintf(fcxx, ")\n{\n%s* __obj = (%s*) ((intptr_t)__imp);\n", c->fullName(), c->fullName()); // If this method registers a callback, find the Arg with the FunctionCType, if any Arg* fct_arg = NULL; @@ -1273,6 +1276,12 @@ if ((m->type->modifiers & CType::M_CTOR) && !(m->type->modifiers & CType::M_PRIVATE)) { + /* + int brk=0; + for (a = m->args; a != NULL && !brk; a = a->next) + if (!strcmp(a->type->classname(),"FunctionCType")) brk=1; + if (brk) break; + */ num_ctors++; fprintf(fcxx, @@ -1281,8 +1290,15 @@ { if (!implicit(a)) { + if (!strcmp(a->type->classname(),"FunctionCType")) { + FunctionCType* fct = (FunctionCType*)a->type; + fct->arg_name = a->name; + fprintf(fcxx, ", %s", + a->type->CTypeName()); + } else { fprintf(fcxx, ", %s %s", a->type->CTypeName(), a->name); + } } } fprintf(fcxx, ") :\n%s(", c->fullName()); @@ -1523,7 +1539,7 @@ subst_typedefs(m, c); } -#if 0 +#if 1 /* If this class does not have an assignment operator defined, we * need to generate a Java method using the C++ default assignment * operator. @@ -1711,6 +1727,27 @@ fprintf(fjava, "package %s;\n", c->dottedPackageName()); } + // Only needed for Java <1.4 + { + Class* parent = c; + while (parent = parent->parentClass()) { + for (Method* m = c->methods; m != NULL; m = m->next) { + if (m->type->modifiers & CType::M_ATTRIBUTE) continue; + for (Method* pm = parent->methods; pm != NULL; pm = pm->next) { + if (pm->type->modifiers & CType::M_ATTRIBUTE) continue; + if (m->hasSameJavaSignature(pm)) { + if (pm->type->JavaTypeName() != NULL && m->type->JavaTypeName() != NULL) { + if (strcmp(pm->type->JavaTypeName(), m->type->JavaTypeName())) { + m->type = pm->type; + } + } + break; + } + } + } + } + } + emit_required_imports(fjava, c); if (import_hook) @@ -1726,9 +1763,32 @@ printf("internal error %s\n", parent->type()->CTypeName()); sp = "Object"; } - fprintf(fjava, "public class %s extends %s {\n", - c->type()->JavaTypeName(), sp); + + /* Need this info here */ + const char* dtor_comment = NULL; + int dtor_protected = 0; + long privpro = CType::M_PROTECTED | CType::M_PRIVATE; + for (m = c->methods; m; m = m->next) + { + if (m->type->modifiers & CType::M_DTOR) + { + dtor_comment = m->comment; + + if (m->type->modifiers & privpro) + { + dtor_protected = 1; + } + } + } + + char* deletable = ""; + if (!c->parentClass() && !dtor_protected) + deletable = " implements org.coin3d.Deletable"; + + fprintf(fjava, "public class %s extends %s%s {\n", + c->type()->JavaTypeName(), sp, deletable); + /* C++ file header. */ fprintf(fcxx, @@ -1860,13 +1920,9 @@ /* Process methods of this class, emitting code as we go. */ - const char* dtor_comment = NULL; int num_ctors = 0; - int dtor_protected = 0; emitted = new StringPool(); - long privpro = CType::M_PROTECTED | CType::M_PRIVATE; - for (m = c->methods; m; m = m->next) { if (m->type->modifiers & CType::M_CTOR) @@ -1875,12 +1931,14 @@ } else if (m->type->modifiers & CType::M_DTOR) { + /* FIXME dtor_comment = m->comment; if (m->type->modifiers & privpro) { dtor_protected = 1; } + */ continue; // skip destructors here } @@ -2011,10 +2069,22 @@ (begin_hook) ? begin_hook : "", (end_hook) ? end_hook : ""); + fprintf(fjava, + "private boolean del_on_gc = false;\n"); + fprintf(fjava, + "/**\n" + " * This method enables automatic garbage collection of the native C++ object\n" + " * when the Java object is garbage collected.\n" + " *\n" + " * @return reference to self (this)\n" + " */\n" + "public %s delOnGc() { if (!del_on_gc) { org.coin3d.RefQ.regGcImpl(new java.lang.ref.WeakReference(this, org.coin3d.RefQ.refq), new %s(implementation)); del_on_gc = true; } return this; }\n", + c->type()->JavaTypeName(), c->type()->JavaTypeName()); + fprintf(fcxx, "JNIEXPORT void JNICALL %s__1_1d(JNIEnv* __env, jobject, jlong __imp)\n" "{\n" - "%s* __obj = (%s*) __imp;\n" + "%s* __obj = (%s*) ((intptr_t)__imp);\n" "delete __obj;\n" "}\n\n", jni_prefix_of_class(c), diff -u cxxwrap-20040103.orig/Method.cxx cxxwrap-20040103/Method.cxx --- cxxwrap-20040103.orig/Method.cxx 2004-01-03 23:15:09.000000000 +0100 +++ cxxwrap-20040103/Method.cxx 2005-01-07 15:30:49.373307200 +0100 @@ -95,6 +95,9 @@ const char* Method::getTextName() { + // Special case for operator- (negate) + if (!strcmp(name, "op-") && args == NULL) return "opNeg"; + String s(name); s.replace('+', "Add"); s.replace('-', "Sub"); @@ -115,8 +118,17 @@ return s.val; } +int Method::hasSameJavaSignature(Method* other) +{ + return hasSameSignature(other, 1); +} int Method::hasSameSignature(Method* other) { + return hasSameSignature(other, 0); +} + +int Method::hasSameSignature(Method* other, int java) +{ if (name != other->name) return 0; Arg* a = args; @@ -125,7 +137,11 @@ while (a) { if (!oa) return 0; - if (!(a->equals(oa))) return 0; + if (java) { + if (!(a->equalsJava(oa))) return 0; + } else { + if (!(a->equals(oa))) return 0; + } a = a->next; oa = oa->next; } diff -u cxxwrap-20040103.orig/Method.h cxxwrap-20040103/Method.h --- cxxwrap-20040103.orig/Method.h 2004-01-03 23:15:09.000000000 +0100 +++ cxxwrap-20040103/Method.h 2005-01-07 15:30:49.373307200 +0100 @@ -68,7 +68,9 @@ const char* getName(); const char* getTextName(); + int hasSameSignature(Method* other, int java); int hasSameSignature(Method* other); + int hasSameJavaSignature(Method* other); const char* name; Arg* args; diff -u cxxwrap-20040103.orig/ObjectCType.cxx cxxwrap-20040103/ObjectCType.cxx --- cxxwrap-20040103.orig/ObjectCType.cxx 2004-01-03 23:15:09.000000000 +0100 +++ cxxwrap-20040103/ObjectCType.cxx 2005-01-07 15:30:49.373307200 +0100 @@ -199,8 +199,10 @@ ObjectCType::JavaUpCast(const char* expr) { char buf[TOKEN_BUFFER_SIZE]; - sprintf(buf, "(%s == 0 ? null : new %s(new Long(%s)))", - expr, JavaTypeName(), expr); + // Enable automatic GC by default for objects we copy from the stack to the heap + int enable_gc = is_object() && (modifiers & (CType::M_POINTER | CType::M_REFERENCE)) == 0; + sprintf(buf, "(%s == 0 ? null : (%s) new %s(new Long(%s))%s)", + expr, JavaTypeName(), JavaTypeName(), expr, enable_gc ? ".delOnGc()" : ""); return global.pool.add(buf); } @@ -469,11 +471,13 @@ " jfieldID __fid = __env->GetFieldID(__env->GetObjectClass(%s), \"implementation\", \"Ljava/lang/Long;\");\n" " jobject __impl_obj = __env->GetObjectField(%s, __fid);\n" " jlong __impl_value = __env->CallLongMethod(__impl_obj, __env->GetMethodID(__env->FindClass(\"java/lang/Long\"), \"longValue\", \"()J\"));\n" - " return %s((%s%s*)__impl_value);\n" + " %s%s* __retval = (%s%s*)__impl_value;\n" + " return %s__retval;\n" "}\n", expr, expr, - deref, CTypeNamePrefix(), BareCTypeName() + CTypeNamePrefix(), BareCTypeName(), CTypeNamePrefix(), BareCTypeName(), + deref ); return global.pool.add(buf); } Common subdirectories: cxxwrap-20040103.orig/doc and cxxwrap-20040103/doc Common subdirectories: cxxwrap-20040103.orig/examples and cxxwrap-20040103/examples diff -u cxxwrap-20040103.orig/main.cxx cxxwrap-20040103/main.cxx --- cxxwrap-20040103.orig/main.cxx 2004-01-03 23:15:09.000000000 +0100 +++ cxxwrap-20040103/main.cxx 2005-01-07 15:30:49.373307200 +0100 @@ -81,6 +81,9 @@ " Enable automatic JNI wrapping of attributes as accessor methods\n" " --jni-operators\n" " Enable automatic JNI wrapping of operators\n" +" --jni-expand-defaults\n" +" Expand C++ methods with default values of parameters into multi-\n" +" ple methods in Java which have no default parameters\n" " --read-cache=\n" " read class cache in .\n" " --write-cache=\n" diff -u cxxwrap-20040103.orig/parser.y cxxwrap-20040103/parser.y --- cxxwrap-20040103.orig/parser.y 2004-01-03 23:15:11.000000000 +0100 +++ cxxwrap-20040103/parser.y 2005-01-07 15:30:49.383321600 +0100 @@ -1459,7 +1459,7 @@ { int i = 0, last = 0; char enum_buf[TOKEN_BUFFER_SIZE]; - while (c != '}' && c != ',' && c != EOF) + while (c != '}' && c != ',' && c != '/' && c != EOF) { // Replace '\n' and '\t' with ' ' if (c == '\n' || c == '\t') c = ' '; Common subdirectories: cxxwrap-20040103.orig/win32 and cxxwrap-20040103/win32