Hello,
I've been playing around with angelscript and ran into a problem with passing classes to script functions. What I want to accomplish is to pass a pointer of an object to a script function, and have the script be able to access the object's methods. The script shouldn't be able to create a new object of this type. Now I'm able to pass the pointer fine and call the methods of the object, but when the object goes out of scope in the script, the object is destroyed. I've registered the ADDREF and RELEASE behaviours, and it seems that the ADDREF isn't called when the object is passed to the script, but RELEASE is called when the object goes out of scope. So the object is then destroyed because the refcount goes to 0. I looked through the test programs, and I can't see anything huge that I'm missing.
This is some code with a very simple class that shows what I'm trying to do:
#include <iostream>
#include <angelscript.h>
class SimpleClass
{
public:
SimpleClass() { m_refcount=1; }
void setint(const int val) { std::cout << "set int to " << val << std::endl; }
void AddRef() { m_refcount++; std::cout << "ref++ = " << m_refcount << std::endl; }
void RemoveRef() { std::cout << "ref-- = " << m_refcount-1 << std::endl; if(--m_refcount==0) { std::cout << "deleting object" << std::endl; delete this; } }
private:
int m_refcount;
};
int main()
{
asIScriptEngine *engine=asCreateScriptEngine(ANGELSCRIPT_VERSION);
engine->RegisterObjectType("simpleclass",0,asOBJ_CLASS);
engine->RegisterObjectBehaviour("simpleclass",asBEHAVE_ADDREF,"void AddRef()",asMETHOD(SimpleClass,AddRef),asCALL_THISCALL);
engine->RegisterObjectBehaviour("simpleclass",asBEHAVE_RELEASE,"void RemoveRef()",asMETHOD(SimpleClass,RemoveRef),asCALL_THISCALL);
engine->RegisterObjectMethod("simpleclass","void setint(const int val)",asMETHOD(SimpleClass,setint),asCALL_THISCALL);
char script[]="void main(simpleclass @obj) { obj.setint(4); }";
int scriptlen=strlen(script);
engine->AddScriptSection(0,"script",script,scriptlen);
engine->Build(0);
asIScriptContext *ctx=engine->CreateContext();
SimpleClass *class1=new SimpleClass;
int funcid=engine->GetFunctionIDByDecl(0,"void main(simpleclass @obj)");
ctx->Prepare(funcid);
ctx->SetArgAddress(0,class1);
std::cout << "BEFORE SCRIPT----" << std::endl;
ctx->Execute();
std::cout << "AFTER SCRIPT-----" << std::endl;
delete class1;
ctx->Release();
engine->Release();
system("PAUSE");
return 0;
}
The output of the program is:
BEFORE SCRIPT----
set int to 4
ref-- = 0
deleting object
AFTER SCRIPT-----
And of course the program crashes when it tries to delete the object again. It's probably something I'm missing with reference counting, but I don't see what's different between this and the test programs. Sure I can call ADDREFF before I pass the object, but I shouldn't have to should I? Can anyone point me in the right direction on how to get this to work?