• Content count

  • Joined

  • Last visited

Community Reputation

242 Neutral

About simong

  • Rank
  1. Wouldn't this return an address pointing to the reference and not to the object itself? It seems that if I print the void* ref from the variable parameter type function it gives me a different address than if I query directly the address using module->GetAddressOfGlobalVar( index );   I might be wrong but it looks like it's doing pretty much the same thing which is giving me a pointer that will not be valid as soon as we are out of the scope of the function. What I'm looking for is a pointer that can outlive that scope, so I can change the value later on.
  2. Hi all,   I'm looking for a way to register some c++ functions and objects that use pointers to manipulate data over time (think UI or animation code). Something along this lines: void createToggle( const string &name, bool *ptr ); void createSlider( const string &name, float *ptr ); void animateValue( float *ptr, float start, float end, float time ); I've been exploring the generic convention api hoping to find something to help me and had a look on the forum, but I can't figure out how to do it.   So let's say that I have this script: float someGlobalValue; void main(){ addSlider( "value", someGlobalValue ); } Is there any way I can register the function and obtain the right pointer from the c++ side? Obviously getting the address using asIScriptGeneric isn't going to work (or maybe I'm missing something). And as far as I know the only way to get this variable address would be to use something like this: int index = module->GetGlobalVarIndexByName( name.c_str() ); if( index >= 0 ){    return mod->GetAddressOfGlobalVar( index ); } I'm totally fine with limiting the system to work only with global variables, if it makes the whole thing easier, but I can't find a way to recover the name of the argument either (from what I can tell asIScriptFunction::GetParam returns the name of the argument as it is in the declaration, not the one passed to the function).   Any advice would be greatly appreciated! (and a solution that could work regardless of the type of the object would be totally amazing (primitive, values and references) )
  3. So here it is! I have the same issue in several part of my code but this one is a good example because the base class is abstract and for this reason unregistrable as a value (because of not being instanciable).   // Source AddRef and Release Behaviors std::map<geom::Source*, uint32_t> sSourceRefs; void sourceAddRef( geom::Source* source ) {     if( !sSourceRefs.count( source ) ){     sSourceRefs[source] = 1; }     else sSourceRefs[source]++; } void sourceRelease( geom::Source* source ) { if( sSourceRefs.count( source ) ){     sSourceRefs[source]--;     if( sSourceRefs[source] == 0 ){     sSourceRefs.erase( sSourceRefs.find( source ) );     //source->~Source();     //delete source;     }     } }   // Conv to geom::Source const geom::Source& sourceConv( const geom::Source& t ){ return t; }   void registerGeom( asIScriptEngine* engine ) {     engine->SetDefaultNamespace( "geom" );              // Source Type (the base class)     engine->RegisterObjectType( "Source", sizeof(geom::Source), asOBJ_REF );       // Source behaviors     engine->RegisterObjectBehaviour( "Source", asBEHAVE_ADDREF, "void f()", asFUNCTION(sourceAddRef), asCALL_CDECL_OBJFIRST );     engine->RegisterObjectBehaviour( "Source", asBEHAVE_RELEASE, "void f()", asFUNCTION(sourceRelease), asCALL_CDECL_OBJFIRST );              // Cube Type (one of the derived classes)     engine->RegisterObjectType( "Cube", sizeof(geom::Source), asOBJ_VALUE | asOBJ_APP_CLASS_CDAK );              // Cube behaviors     Script::registerConstructor<geom::Cube>( engine, "Cube" );     Script::registerDestructor<geom::Cube>( engine, "Cube" );     Script::registerCopyConstructor<geom::Cube>( engine, "Cube" );     Script::registerCopyAssignment<geom::Cube>( engine, "Cube" );       engine->RegisterObjectMethod( "Cube", "const geom::Source& opImplConv() const", asFUNCTION( sourceConv ), asCALL_CDECL_OBJLAST );                   engine->SetDefaultNamespace( "" ); }   So basically there is a series of geometric objects like geom::Cube, geom::Sphere, geom::Plane, etc... and all of them inherit from the base class geom::Source. The only reason to expose geom::Source is that a lot of other functions takes a const Source& as inputs. I'd love to be able to rely on some sort of polymorphism and not have to register the different functions several time for each type of geom classes.
  4. Thanks Andreas.     I thought opConv and opImplConv were a replacement for the depreciated value cast behavior. If we take the aswrapper test.cpp as an example, how would you replace the conversion code that starts at line 140? Would opConv and opImplConv be the way to go?     Ok, I think I'm getting slowly the idea :)   So I did experiment a bit more with this. I tried to register an addRef and release behavior to my base class. Here's what I think is happening when the conversion happen. So basically I pass a Derived object to a function as a &in reference. When this happen and my opImplConv is executed, the addRef of the base class is called and the refcounting starts. Directly after the engine call the release function where I check if the pointer is correct and if the refcount is at zero I try to delete the object. I think at that point that the address is actually pointing to the actual Derived object and not a copy, which would explain why it crash if I delete the object when it's released... So if I'm getting it correctly, in this case it's not exactly a copy of the object but a reference. Is that right?    Would that help if I post some code?   Thanks a lot anyway and sorry for being slow at understanding how this work!
  5. Great, thanks a lot for the explanation!   Last question though, does it means that giving a "const RefBase& opImplConv( )" to a Value type can potentially solve the whole "safe/copy" issue you are explaining above? 
  6. Alright, so I did some more tests and it seems that I managed to find a solution that works, but I was curious to still hear your opinion;   Would registering the base type as a asOBJ_REF | asOBJ_NOCOUNT with no factory or behaviors be something wrong?
  7. Hi Andreas,   I have a quick question about polymorphic types.   I'm trying to register a series of functions that accepts a const reference to an abstract class and I'd love to find a way to make it work like in c++, being able to implicitly cast a Derived class to a const reference of the base class. Something like this :   class Base { // abstract with no public constructors };   class DerivedA : public Base { }; class DerivedB : public Base { }; class DerivedC : public Base { }; class DerivedD : public Base { }; class DerivedE : public Base { };   void someFunction( const DerivedA &obj );   My objects are registered as Values making it difficult I guess to find a solution to my problem. The first issue of course is that the Base class usually doesn't have a public default constructor, which trigger an error message when trying to register the type. I managed to make it run by registering the base type as POD (this is probably totally wrong). Secondly I added to the Derived classes an opImplConv operator. Everything compiles fine without any error messages, but somehow when converted and then passed to the function the object seems to be empty and usually make the application crash.    I don't know if I've been really clear but if you have any advices other than re-implementing everything as Ref types I'd be really grateful.   Thanks in advance, Simon.
  8. Works perfectly! Thanks Andreas.
  9. Hi all,   I'm having some issue trying to register two enums that have the same name. One is in the global namespace and the other lives inside a class. I thought that I could register the second one by using a namespace but apparently I still got some name collision errors.   I just stumbled upon this thread and though this was fixed a long time ago, but I think the issue I'm having might still be related because I still have errors when one of the two enums is living in the global namespace. Here's an example.   The c++ enums I'd like to register:   enum {     VALUE_A,     VALUE_B } Enum;   namespace enum_ns {     enum {         VALUE_A,         VALUE_B     } Enum; }   And here's the code I'm trying to use to register the two enums.   engine->RegisterEnum( "Enum" ); engine->RegisterEnumValue( "Enum", "VALUE_A", Enum::VALUE_A ); engine->RegisterEnumValue( "Enum", "VALUE_B", Enum::VALUE_B );   engine->SetDefaultNamespace( "enum_ns" ); engine->RegisterEnum( "Enum" ); engine->RegisterEnumValue( "Enum", "VALUE_A", enum_ns::Enum::VALUE_A ); engine->RegisterEnumValue( "Enum", "VALUE_B", enum_ns::Enum::VALUE_B ); engine->SetDefaultNamespace( "" );   If I try to execute this I have this error message; And as Code:-13 suggests things that have already been registered I guess the scope of the Enum can't be solved correcly.    (0, 0) : ERR  : Failed in call to function 'RegisterEnum' with 'Enum' (Code: -1)  (0, 0) : ERR  : Failed in call to function 'RegisterEnumValue' with 'Enum' and 'VALUE_A' (Code: -13)  (0, 0) : ERR  : Failed in call to function 'RegisterEnumValue' with 'Enum' and 'VALUE_B' (Code: -13)  (0, 0) : ERR  : Invalid configuration. Verify the registered application interface.   The funny thing is that if I do it the other way around and register the non-global one first, I don't have any error message. Unfortunately in the application I'm working on I can't really predict in what order this is going to be registered, so I'm afraid this doesn't really help!   I'm not sure if I can think of an other alternative. Has someone already experienced this before? Am I doing something wrong?   Thanks a lot for any suggestions.   Simon.
  10. That's great! Thanks a lot Andreas.
  11. Thanks, This makes sense but wouldn't it be useful to have an alternative when you know what you are doing? I mean if you deliberately write a bool operator in your class, I guess it is probably because you want your class to behave differently and it means that the conversion to bool is well defined as well.   I don't know maybe in this case adding an opBool to the language would make more sense?
  12. Hi,   I've got a lot of shared_ptr underneath my script objects and because of the new features of 2.29.2 I wanted to try registering the handy "operator bool" that allow testing shared_ptr like this : if( myShared ){ }  For some reason I can't make opConv or opImplConv to work for booleans. To make sure I wasn't doing something stupid on the c++ side, I tried doing the same in the script using the code provided in the documentation but without success.   It is an extremely useful feature of shared_ptr in c++ and I'd love to be able to expose the same feature for the classes I register to angelscript.   Here's what I tried in c++ : engine->RegisterObjectMethod( "ObjectRef", "bool opImplConv() const", asMETHODPR(ObjectRef, operator bool, () const, bool ), asCALL_THISCALL );  and in Angelscript: class MyObj { double myValue; double opImplConv() const { return myValue; } bool opImplConv() const { return myValue > 0; } // bool opConv() const { return myValue > 0; } }; MyObj c; c.myValue = 0.12345; double cDouble = c; // this works bool cBool = c; // this doesn't and gives "MainSection (66, 16) : ERR : Can't implicitly convert from 'MyObj&' to 'bool'." Is this a limitation of the new conversion operator or am I missing something obvious?   Thanks in advance! Simon.
  13. Oh my god! You're right! I'm not sure how I missed that out! Thank you so much!   And thanks for looking into it so quickly!
  14. I tried the rev 1858 (and the release 2.28.0 & 2.28.1) and unfortunately it doesn't change anything.    I also tried several combination of asOBJ_APP_CLASS_* without any luck, but I did find that it doesn't reach the assertion failed if the type is declared only as asOBJ_VALUE | asOBJ_POD.   I tried to make a test as short as possible that still make the application crash: // Register the class itself r = engine->RegisterObjectType( "Vec2f", sizeof(Vec2f_), asOBJ_VALUE | asOBJ_APP_CLASS_CDAK ); assert( r >= 0 ); // Vec2f() r = engine->RegisterObjectBehaviour( "Vec2f", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(as::BindingHelper::constructor<Vec2f_>), asCALL_CDECL_OBJLAST); assert( r >= 0 ); // Vec2f( const Vec2f& src ) r = engine->RegisterObjectBehaviour( "Vec2f", asBEHAVE_CONSTRUCT, "void f(const Vec2f &in )", asFUNCTION((as::BindingHelper::constructor<Vec2f_,Vec2f_&>)), asCALL_CDECL_OBJLAST); assert( r >= 0 ); // ~Vec2f() r = engine->RegisterObjectBehaviour("Vec2f", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(as::BindingHelper::destructor<Vec2f_>), asCALL_CDECL_OBJLAST); assert( r >= 0 ); // Vec2f& operator=( const Vec2f& rhs ) r = engine->RegisterObjectMethod("Vec2f", "Vec2f opAssign(const Vec2f &in)", asFUNCTION((as::BindingHelper::opAssign<Vec2f_,Vec2f_,Vec2f_>)), asCALL_CDECL_OBJLAST); assert( r >= 0 ); I replaced the original Vec2f class by a dummy one just to be sure (the original class contains all the functions registered above): class Vec2f_ { }; And here's the script: Vec2f t; void main(){ test( t ); } void test( const Vec2f &in v ){} The "as::BindingHelper" above is using the exact same code as the class helper that you can find on the wiki.   Here's the full callstack if it's of any help:  
  15. I'm still quite new to Angelscript and I have some trouble understanding what's going here.   I'm trying to pass a global variable in my script to a function that accept a const & parameter. Things seems to work as expected when I use a primitive or a class declared in the same script, but as soon as I'm trying to do this with a type I registered from the application I run directly into a failed assertion:   Assertion failed: (useVariable), function PerformFunctionCall, file [...]/angelscript/source/as_compiler.cpp, line 12833. if( descr->returnType.IsObject() && !descr->returnType.IsReference() ){ int returnOffset = 0; if( descr->DoesReturnOnStack() ){ asASSERT( useVariable ); // The variable was allocated before the function was called returnOffset = varOffset; ctx->type.SetVariable(descr->returnType, returnOffset, true); // The variable was initialized by the function, so we need to mark it as initialized here ctx->bc.ObjInfo(varOffset, asOBJ_INIT); } It really seems to be related to the fact that the variable I'm trying to pass as a parameter is global and from a custom type. I tried doing the same inside a class and I don't have any problem. As explained above I don't have this issue with primitives or types created in the script, so my first guess would be that I'm doing something wrong with the registration. Which is probably the case as this is the first class I'm trying to register to AS.   I'm registering my type as asOBJ_VALUE and asOBJ_APP_CLASS_CDAK.   Here's an example code to illustrate what I'm doing. float test1; Vec2f test2; // Vec2f is the registered type void main(){ // main is the function called testFloat( test1 ); // works testVec2f( test2 ); // crash with "Assertion Failed" } void testFloat( const int &param ){} void testVec2f( const Vec2f &in param ){} // the two following work without surprise but I would really prefer // keeping the const correctness of the class I register to AS void stupidTestVec2f( const Vec2f param ){} void stupidTest2Vec2f( Vec2f param ){} I guess it is somehow related to the way I register my Vec2f type, but I can't seem to find the correct way and I've tried to find solution here without success.   As a side question, is "const T &in" the closest to what "const T &" means in c++?   Thanks! Simon.