#include "angelscript.h"
#include <string>
#include <iostream>
struct Foo
{
Foo() {}
~Foo() {}
Foo(const Foo& rhs) {}
Foo& operator=(const Foo& rhs) { return *this; }
};
//THIS CRASHES.
std::string foo_member_fun_one(const std::string& in, Foo* thisp)
{
std::cout << "foo_member_fun_one: " << in << "\n";
return in;
}
void foo_member_fun_two(const std::string& in, Foo* thisp)
{
std::cout << "foo_member_fun_two: " << in << "\n";
}
std::string free_fun(const std::string& in)
{
std::cout << "free_fun: " << in << "\n";
return in;
}
void ConstructFoo(Foo* ptr) { new (ptr) Foo(); }
void CopyConstructFoo(const Foo& rhs, Foo* ptr) { new (ptr) Foo(rhs); }
void DestroyFoo(Foo* ptr) { ptr->~Foo(); }
Foo& AssignFoo(const Foo& rhs, Foo* ptr) { return (*ptr) = rhs; }
void ConstructString(std::string* ptr) { new (ptr) std::string(); }
void CopyConstructString(const std::string& rhs, std::string* ptr) { new (ptr) std::string(rhs); }
void DestroyString(std::string* ptr) { ptr->~basic_string(); }
std::string& AssignString(const std::string& rhs, std::string* ptr) { return (*ptr) = rhs; }
std::string StringFactory(unsigned int length, const char *s)
{
std::cout << "StringFactory: " << std::string(s,length) << "\n";
return std::string(s,length);
}
int main(int argc, char* argv[])
{
asIScriptEngine* engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
int error_code = 0;
std::cout << "Registering Foo. ";
error_code = engine->RegisterObjectType("Foo",sizeof(Foo),asOBJ_CLASS_CDA);
if (error_code < 0) std::cout << "Error: " << error_code;
std::cout << "\nRegistering Foo constructor. ";
error_code = engine->RegisterObjectBehaviour("Foo",
asBEHAVE_CONSTRUCT,
"void constructor()",
asFUNCTION(ConstructFoo),
asCALL_CDECL_OBJLAST);
if (error_code < 0) std::cout << "Error: " << error_code;
std::cout << "\nRegistering Foo destructor. ";
error_code = engine->RegisterObjectBehaviour("Foo",
asBEHAVE_DESTRUCT,
"void destructor()",
asFUNCTION(DestroyFoo),
asCALL_CDECL_OBJLAST);
if (error_code < 0) std::cout << "Error: " << error_code;
std::cout << "\nRegistering Foo operator=. ";
error_code = engine->RegisterObjectBehaviour("Foo",
asBEHAVE_ASSIGNMENT,
"Foo& op_assign(const Foo&)",
asFUNCTION(AssignFoo),
asCALL_CDECL_OBJLAST);
if (error_code < 0) std::cout << "Error: " << error_code;
std::cout << "\nRegistering Foo copy constructor. ";
error_code = engine->RegisterObjectBehaviour("Foo",
asBEHAVE_CONSTRUCT,
"void constructor(const Foo&)",
asFUNCTION(CopyConstructFoo),
asCALL_CDECL_OBJLAST);
if (error_code < 0) std::cout << "Error: " << error_code;
std::cout << "\nRegistering string. ";
error_code = engine->RegisterObjectType("string",sizeof(std::string),asOBJ_CLASS_CDA);
if (error_code < 0) std::cout << "Error: " << error_code;
std::cout << "\nRegistering string constructor. ";
error_code = engine->RegisterObjectBehaviour("string",
asBEHAVE_CONSTRUCT,
"void constructor()",
asFUNCTION(ConstructString),
asCALL_CDECL_OBJLAST);
if (error_code < 0) std::cout << "Error: " << error_code;
std::cout << "\nRegistering string destructor. ";
error_code = engine->RegisterObjectBehaviour("string",
asBEHAVE_DESTRUCT,
"void destructor()",
asFUNCTION(DestroyString),
asCALL_CDECL_OBJLAST);
if (error_code < 0) std::cout << "Error: " << error_code;
std::cout << "\nRegistering string operator=. ";
error_code = engine->RegisterObjectBehaviour("string",
asBEHAVE_ASSIGNMENT,
"string& op_assign(const string&)",
asFUNCTION(AssignString),
asCALL_CDECL_OBJLAST);
if (error_code < 0) std::cout << "Error: " << error_code;
std::cout << "\nRegistering string copy constructor. ";
error_code = engine->RegisterObjectBehaviour("string",
asBEHAVE_CONSTRUCT,
"void constructor(const string&)",
asFUNCTION(CopyConstructString),
asCALL_CDECL_OBJLAST);
if (error_code < 0) std::cout << "Error: " << error_code;
std::cout << "\nRegistering string factory. ";
error_code = engine->RegisterStringFactory("string",
asFUNCTION(StringFactory),
asCALL_CDECL);
if (error_code < 0) std::cout << "Error: " << error_code;
std::cout << "\nRegistering Foo member fun one. ";
error_code = engine->RegisterObjectMethod("Foo",
"string member_one(const string&)",
asFUNCTION(foo_member_fun_one),
asCALL_CDECL_OBJLAST);
if (error_code < 0) std::cout << "Error: " << error_code;
std::cout << "\nRegistering Foo member fun two. ";
error_code = engine->RegisterObjectMethod("Foo",
"void member_two(const string&)",
asFUNCTION(foo_member_fun_two),
asCALL_CDECL_OBJLAST);
if (error_code < 0) std::cout << "Error: " << error_code;
std::cout << "\nRegistering free fun. ";
error_code = engine->RegisterGlobalFunction(
"string free_fun(const string&)",
asFUNCTION(free_fun),
asCALL_CDECL);
if (error_code < 0) std::cout << "Error: " << error_code;
std::string script = "void test(Foo f) { free_fun(\"foo\"); f.member_two(\"foo\"); f.member_one(\"foo\"); }";
engine->AddScriptSection(0,"test",script.c_str(),script.length());
std::cout << "\nBuilding test script. ";
error_code = engine->Build(0);
if (error_code < 0) std::cout << "Error: " << error_code;
std::cout << "\nGetting function id. ";
int func_id = engine->GetFunctionIDByName(0,"test");
if (func_id < 0) std::cout << error_code;
asIScriptContext* ctx = engine->CreateContext();
std::cout << "\nPreparing context. ";
error_code = ctx->Prepare(func_id);
if (error_code < 0) std::cout << "Error: " << error_code;
Foo f;
std::cout << "\nSetting parameter. ";
error_code = ctx->SetArgObject(0,&f);
if (error_code < 0) std::cout << "Error: " << error_code;
std::cout << "\nCalling script.\n";
error_code = ctx->Execute();
if (error_code != asEXECUTION_FINISHED) std::cout << "Error: " << error_code;
std::cout << "\n\nFin.";
return 0;
}
🎉 Celebrating 25 Years of GameDev.net! 🎉
Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!
member functions that return an object gets invalid parameter
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game
I traced the problem down to when angelscript calls the destructor on the object during a temporary copy of some sort, which I attributed to cross module boundary object lifetime issues.
My issue may however be unrelated.
Doing this will make sure AngelScript uses the same heap for memory allocation as the application.
See the following functions for more info:
engine::SetCommonObjectMemoryFunctions()
engine::RegisterObjectBehaviour() with behaviours asBEHAVE_ALLOC and asBEHAVE_FREE
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game
Actually in your other thread you mentioned something that could be related to the memory management, so I intended the response for both of you. Mostly as something to think about.
I still pretend to test the problem you reported in this thread, but I haven't had the time to do so yet.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game
Anyway, I found the bug. It's an old bug so I'm a bit surprised that it hasn't shown up before. On line 260 in as_callfunc_x86.cpp the function pointer is initialized incorrectly. It should be:
const t_CallCDeclObjRetByRef CallCDeclFunctionRetByRefObjLast = (t_CallCDeclObjRetByRef)CallCDeclFunctionRetByRefObjLast_impl;
Regards,
Andreas
[edit]Updated file name[/edit]
[Edited by - WitchLord on January 13, 2006 7:12:39 AM]
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game