Advertisement

Object handle problem

Started by December 13, 2005 02:29 PM
3 comments, last by WitchLord 18 years, 11 months ago
Sorry, come back with this one :) I've a class pointer allocated in c++ code. I want to allow scripts to get this pointer to handle it, but don't allow script to create instance of that class. So in c part, I've something like :

class MyClass
{
public:
  MyClass() : m_refCount( 1 ) {}
  int m_refCount;
  ... AddRef() & Release()
}

MyClass* GetMyClassPtr()
{
  if( g_pMyClass )
    g_pMyClass->AddRef();

  return g_pMyClass;
}
...
// somewhere in the asEngine registering part
  pEngine->RegisterObjectType( "MyClass", 0, asOBJ_CLASS ); // no C D or A since I don't want script to create it
  pEngine->RegisterObjectBehaviour( "MyClass", asBEHAVE_ADDREF, "void f()", asMETHODPR(Myclass, AddRef, (), void), asCALL_THISCALL );
 pEngine->RegisterObjectBehaviour( "MyClass", asBEHAVE_RELEASE, "void f()", asMETHODPR(MyClass, Release, (), void), asCALL_THISCALL );
  pEngine->RegisterGlobalFunction( "MyClass@ GetMyClassPtr()", asFUNCTION(GetMyClassPtr), asCALL_CDECL );


Then in the script :

void main()
{
  MyClass@ pMyClass = GetMyClassPtr();
}


Then, after running the script, I run in crash... (seems to be a bad pointer access). After some tries, I found that after running the script, the refCount of g_pMyClass is 0, so I guess it has been deleted (by the Release() method), but why ? I stepped into GetMyClassPtr() and after calling AddRef(), the refCount is 2. I also tried to add assignment operator, but same result. I could make it reference instead of object handle, but i would be able to assign a variable later than in its declaration like :

  MyClass& pMyClass;
  ...
  pMyClass = GetMyClassPtr();


which is what I want (and what's worked well with pointers :)). Any Idea ? Lbas
Lbas
Hmm...

I'll have to make some tests. I can't see any obvious error in your code. You may actually have discovered another bug.

Would it be possible for you to put up the bytecode generated for the script function? If you have compiled the script library with AS_DEBUG, it will generate text files for all the bytecodes it generates.

Does the script work if you separate the variable declaration and initialization?

void main(){  MyClass@ pMyClass;  pMyClass = GetMyClassPtr();}


Probably unrelated to your problem, but I suggest that you use the flag asOBJ_CLASS_CDA (if you indeed have the destructor and assignment operator defined), even though you registered the type with a size of 0. This flag should always accurately describe the C++ class, as it tells AngelScript how to correctly handle the type when interacting with application registered functions. It shouldn't make any differences in this case because you'll always be passing the type around as a pointer, but I think it is a good idea to always set the flag correctly anyway. It could help you minimize problems if you later change the configuration.

Regards,
Andreas

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement
Hi,
I tried both advices, and still occur.
I tried to remove the "delete" from the Release() method and it still crashes, so maybe the crash has no relation with this problem, but it's still get refCount to 0.
I'll continue investigate on it, trying to isolate a test projet and let you knwo the issue (also giving you the requested debug files).

See you later :)
Lbas
Lbas
I finally found the problem.

What I was trying to do is to create a base class which handle AddRef(), Release() and Assignment() without having to do it on each registered class. Most of the registered classes already inherit from other class, and the problem comes from that point. All works fine if I call AddRef() from the C part, but when AddRef() is called from the script the 'this' pointer is bad (seems to points on second derived class). To help understand, let me introduce a pseudo-example :

class cScriptBase{  public:    cScriptBase() : m_nRefCount( 1 ) {}    void AddRef() {m_nRefCount++;}    void Release()    {      if( (--m_nRefCount) == 0 )        delete this;    }  private:    int m_nRefCount;}class MyClass : public cScriptBase, AnotherClass{  static void Register( asIScriptEngine* pEngine );  ...}void MyClass::Register( asIScriptEngine* pEngine ){  ...  pEngine->RegisterObjectBehaviour( "MyClass", asBEHAVE_ADDREF, "void f()", asMETHODPR(MyClass, AddRef, (), void), asCALL_THISCALL );  }


When I step into AddRef(), the 'this' pointer seems to points somewhere in the AnotherClass part. I tried to register cScriptBase::AddRef() instead of MyClass::AddRef() but same result.
Today, the only workaround I found is to move the AddRef()/Release() in the MyClass declaration using some DECLARE_SCRIPT_BASE() / IMPLEMENT_SCRIPT_BASE()macros.

[EDIT: I guess it's related to the asMETHOD() serie macros, but don't know why nor how to solve it (and can't spend any more time on this, sorry for that)]

Am I missing something ?
Maybe I'll try to make cScriptBase template.

Regards,
Lbas
Lbas
Have you tried declaring the AddRef() and Release() methods in cScriptBase as virtual methods?

AngelScript should be able to handle class methods for multiple inheritance, but it could be that since you didn't declare the methods as virtual, the method pointer doesn't hold enough information for AngelScript to resolve the true this pointer.

I'll try to see if I can reproduce this problem and see if there is something I can do in AngelScript to fix it.

Regards,
Andreas


AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This topic is closed to new replies.

Advertisement