Calling Script Function with by value types

Started by
8 comments, last by jedjed 14 years, 1 month ago
Hi I'm having an issue when I try to call this script function: r = mEngine->RegisterObjectType("Entity", sizeof(IEntityPtr), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CDA ); bool entityCallback(IEntityPtr perm) { int id=mModule->GetFunctionIdByDecl("bool entityCallback(Entity)"); mContext->Prepare(id); mContext->SetArgObject(0, &perm); int r = mContext->Execute(); } mContext->Execute(); returns -1 even if the implementation in the script is empty. Just: bool entityCallback(Entity ent) { return(true); } What am I doing wrong?
Advertisement
Is IEntityPtr a smart pointer? If so, then it shouldn't be registered as asOBJ_POD and you should also register object behaviors like construct, destroy and assign.
It is a boost::shared_ptr. Can't that be treated as a asOBJ_POD ?
No, boost::shared_ptr needs to adjust reference counts when being copied and destroyed.
Under what circumstances can you use asOBJ_POD?


[Edited by - jedjed on March 18, 2010 1:31:14 AM]
So I've tried this many different ways but it still isn't working. What is the proper way to do this?

I want my app to call a script function and pass it what is a shared_ptr in my app. This shared_ptr will obviously exist for the length of the call into the script and the scripts wont use it outside of the call. So it seems like the memory management stuff isn't necessary.

But if it still is how do I create the value type properly when the value is a shared_ptr in my app?
asOBJ_POD can be used when the object is a POD type. Primitives are POD and a C++ class type is POD when it has no user defined constructor, destructor or assignment operator and also doesn't contain any non-POD members. boost::shared_ptr isn't POD because it defines constructors, a destructor and an assignment operator. To register a shared_ptr properly you'll to register it as a value type without the asOBJ_POD flag, as well as register the asBEHAVE_CONSTRUCT and asBEHAVE_DESTRUCT object behaviors and the opAssign object method.
Sorry to keep asking about this. The -1 thing was because I was calling the script function using an active context. Now that is fixed but now I'm getting garbage for the value types when they are passed back to my app.

So I must not be registering the Constructor,Destructor or assignment correctly. This is what I'm doing:

typedef boost::shared_ptr<IEntity> IEntityPtr;
r = mEngine->RegisterObjectType("Entity", sizeof(IEntityPtr), asOBJ_VALUE | asOBJ_APP_CLASS_CDA );

r = mEngine->RegisterObjectBehaviour("Entity", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(IEntityPtrConstructor), asCALL_CDECL_OBJLAST);

r = mEngine->RegisterObjectBehaviour("Entity", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(IEntityPtrDestructor), asCALL_CDECL_OBJLAST);

r = mEngine->RegisterObjectMethod("Entity", "Entity &opAssign(const Entity &in)", asMETHODPR(IEntityPtr, operator=, (const IEntityPtr&), IEntityPtr&), asCALL_THISCALL);

void IEntityPtrConstructor(void* memory)
{
new(memory) IEntityPtr();
}

void IEntityPtrDestructor(void* memory)
{
((IEntityPtr*)memory)->~IEntityPtr();
}
How are you passing them back to your application? This works for me:
#include "angelscript.h"#include "scriptstdstring.h"#include <iostream>#include <cassert>#include <cstdio>#include <boost/shared_ptr.hpp>struct Test {  int data;};typedef boost::shared_ptr<Test> TestPtr;template <typename T>void construct(void * memory) {  new (memory) T();}template <typename T>void destroy(void * memory) {  ((T *)memory)->~T();}void MessageCallback(const asSMessageInfo *msg, void *param){	const char *type = "ERR ";	if( msg->type == asMSGTYPE_WARNING ) 		type = "WARN";	else if( msg->type == asMSGTYPE_INFORMATION ) 		type = "INFO";	printf("%s (%d, %d) : %s : %s\n", msg->section, msg->row, msg->col, type, msg->message);}void print(std::string & str) {	std::cout << str;}int main(int, char **) {  asIScriptEngine * engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);  engine->SetMessageCallback(asFUNCTION(MessageCallback), 0, asCALL_CDECL);  RegisterStdString(engine);    int r;    r = engine->RegisterObjectType("TestPtr", sizeof(TestPtr), asOBJ_VALUE | asOBJ_APP_CLASS_CDA); assert(r >= 0);  r = engine->RegisterObjectBehaviour("TestPtr", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(construct<TestPtr>), asCALL_CDECL_OBJLAST); assert(r >= 0);  r = engine->RegisterObjectBehaviour("TestPtr", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(destroy<TestPtr>), asCALL_CDECL_OBJLAST); assert(r >= 0);  r = engine->RegisterObjectMethod("TestPtr", "TestPtr & opAssign(const TestPtr & in)", asMETHODPR(TestPtr, operator=, (const TestPtr &), TestPtr &), asCALL_THISCALL); assert(r >= 0);  r = engine->RegisterGlobalFunction("void print(string & in)", asFUNCTION(print), asCALL_CDECL); assert( r >= 0 );    const char script[] =    "TestPtr foo(TestPtr t) {\n"    "  return t;\n"    "}\n"  ;      asIScriptModule * mod = engine->GetModule(0, asGM_ALWAYS_CREATE);  r = mod->AddScriptSection("script", script, sizeof(script) - 1); assert(r >= 0);  r = mod->Build(); assert(r >= 0);  int func_id = mod->GetFunctionIdByDecl("TestPtr foo(TestPtr t)"); assert(func_id >= 0);  asIScriptContext * ctx = engine->CreateContext();  TestPtr test(new Test);    test->data = 5;  r = ctx->Prepare(func_id); assert(r >= 0);  r = ctx->SetArgObject(0, &test); assert(r >= 0);  r = ctx->Execute(); assert(r >= 0);  TestPtr ret_val = *((TestPtr *)ctx->GetAddressOfReturnValue());  std::cout << ret_val->data << std::endl;    assert(test.get() == ret_val.get());  ctx->Release();  engine->Release();}
Ok perfect thanks. Everything is working now. Great thing you guys made

This topic is closed to new replies.

Advertisement