Advertisement

Basic Class Declaration in Multiple Files

Started by September 05, 2011 04:04 AM
3 comments, last by BrianEmpson 13 years, 2 months ago
Hello,

I'm trying to do something simple, I declared a class in "entity.as" that I want to use in "main.as".

Entity.as:

class Entity
{
Entity()
{
bIsVisible = false;
}

~Entity()
{
}

void Tick()
{
print("This is Entity::Tick()!!");
int clientFD;
int port = 9000;
clientFD = clientSock("127.0.0.1",9000);
sendPacket(clientFD,"This is the entity script!");
}
//Properties
bool bReplicate; //Do we send this out via the network?
bool bIsVisible; //Is this object visible during play?
}


main.as:

void main()
{
TICKRATE = 25;
g_GAMEMODE = GM_STANDALONE;
Entity test;
test.Tick();
print("This is void main()!\n");
}


The application compiles entity.as and then main.as, which is where it fails with:


MSG_CALLBACK: ../../release/data/scripts/main.as (1, 1) : INFO : Compiling void main()
MSG_CALLBACK: ../../release/data/scripts/main.as (5, 5) : ERR : Identifier 'Entity' is not a data type


What am I missing for this simple script to work?

Thanks, I could not find a clear example of why this would not work in the manual...

Hello,

I'm trying to do something simple, I declared a class in "entity.as" that I want to use in "main.as".

Entity.as:

class Entity
{
Entity()
{
bIsVisible = false;
}

~Entity()
{
}

void Tick()
{
print("This is Entity::Tick()!!");
int clientFD;
int port = 9000;
clientFD = clientSock("127.0.0.1",9000);
sendPacket(clientFD,"This is the entity script!");
}
//Properties
bool bReplicate; //Do we send this out via the network?
bool bIsVisible; //Is this object visible during play?
}


main.as:

void main()
{
TICKRATE = 25;
g_GAMEMODE = GM_STANDALONE;
Entity test;
test.Tick();
print("This is void main()!\n");
}


The application compiles entity.as and then main.as, which is where it fails with:


MSG_CALLBACK: ../../release/data/scripts/main.as (1, 1) : INFO : Compiling void main()
MSG_CALLBACK: ../../release/data/scripts/main.as (5, 5) : ERR : Identifier 'Entity' is not a data type


What am I missing for this simple script to work?

Thanks, I could not find a clear example of why this would not work in the manual...


Well since you didn't provide any information about how you load these scripts, I'm going to assume you are loading them into two separate modules. Modules can't share classes between them, instead you need to load all sections into the same module:


asIScriptModule *Mod = asEngine->GetModule(0, asGM_ALWAYS_CREATE);
Mod->AddScriptSection("Entity.as", entitySource, entitySource.size());
Mod->AddScriptSection("Main.as", mainSource, mainSource.size());

...


You might want to look into the scriptbuilder add-on which includes a implementation of a include preprocessor. The preprocessor works just like it does in C or C++.

- Jeremy
Advertisement
They are loaded into the same module with the following code:



//Prototypes for functions are above...

int main()
{
//Snipped...
asBuildScript(config->engine,"entity.as");
asBuildScript(config->engine,"main.as");
asRunFunc(config->engine,"void compile_scripts()");
asRunMethod(config->engine,"Entity","void Tick()");
asRunFunc(config->engine,"void main()");
//Snipped
return 0;
}

void asBuildScript(asIScriptEngine *engine, std::string name)
{
u32 r;
CScriptBuilder builder;
r = builder.StartNewModule(engine, "scriptModule");
if( r < 0 )
{
// If the code fails here it is usually because there
// is no more memory to allocate the module
cout<<"Unrecoverable error while starting a new module.\n";
return;
}
r = builder.AddSectionFromFile(name.c_str());
if( r < 0 )
{
// The builder wasn't able to load the file. Maybe the file
// has been removed, or the wrong name was given, or some
// preprocessing commands are incorrectly written.
cout<<"Please correct the errors in the script and try again.\n";
return;
}
r = builder.BuildModule();
if( r < 0 )
{
// An error occurred. Instruct the script writer to fix the
// compilation errors that were listed in the output stream.
cout<<"Please correct the errors in the script and try again.\n";
return;
}
return;
}

void asRunFunc(asIScriptEngine *engine,std::string name)
{
u32 r;
// Find the function that is to be called.
asIScriptModule *mod = engine->GetModule("scriptModule");
int funcId = mod->GetFunctionIdByDecl(name.c_str());
if( funcId < 0)
{
// The function couldn't be found. Instruct the script writer
// to include the expected function in the script.
cout<<"Function " << name << " not found. Please add it and try again.\n";
return;
}

// Create our context, prepare it, and then execute
asIScriptContext *ctx = engine->CreateContext();
ctx->Prepare(funcId);
r = ctx->Execute();
if( r != asEXECUTION_FINISHED)
{
// The execution didn't complete as expected. Determine what happened.
if( r == asEXECUTION_EXCEPTION)
{
// An exception occurred, let the script writer know what happened so it can be corrected.
cout<<"An exception " << ctx->GetExceptionString() << " occurred. Please correct the code and try again.\n";
}
}
// Clean up
ctx->Release();
return;
}

void asRunMethod(asIScriptEngine *engine,std::string object,std::string name)
{
asIScriptContext *ctx = engine->CreateContext();

// Get the object type
asIScriptModule *module = engine->GetModule("scriptModule");
asIObjectType *type = engine->GetObjectTypeById(module->GetTypeIdByDecl(object.c_str()));
if (type == 0)
{
cout<<"Error instancing class "<< object <<".\n";
return;
}

std::string decl = object + " @" + object + "()";

// Get the factory function id from the object type
int factoryId = type->GetFactoryIdByDecl(decl.c_str());

// Prepare the context to call the factory function
ctx->Prepare(factoryId);

// Execute the call
ctx->Execute();

// Get the object that was created
asIScriptObject *obj = *(asIScriptObject**)ctx->GetAddressOfReturnValue();
if (obj == 0)
{
cout<<"Unable to get object return value for " << object << ".\n";
return;
}

// If you're going to store the object you must increase the reference,
// otherwise it will be destroyed when the context is reused or destroyed.
obj->AddRef();

// Obtain the id of the class method
int funcId = type->GetMethodIdByDecl(name.c_str());

// Prepare the context for calling the method
ctx->Prepare(funcId);

// Set the object pointer
ctx->SetObject(obj);

// Execute the call
ctx->Execute();

return;
}



I will try the add script section code...
Your asBuildScript is creating a new module for each script file. This is why the script "main.as" doesn't see the class in "entity.as".

However, as you're already using the CScriptBuilder you can just remove the first line with asBuildScript(config->engine,"entity.as");, and instead add #include "entity.as" in the script "main.as".

The CScriptBuilder will then include the "entity.as" in the same module as the "main.as", which is what you were trying to do.

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

Thank you,

I have fixed it after realizing the above problem...Now the code looks like this:


//in main()
r = config->builder.StartNewModule(config->engine, "scriptModule");
if( r < 0 )
{
cout<<"Unrecoverable error while starting script module.\n";
//Should we exit here?
}

//Build function now builds all files in a list at once...in the same module
void asBuildScripts()
{
s32 r;
//r = builder.StartNewModule(config->engine, "scriptModule");
//config->mod = engine->GetModule("scriptModule");
for (u32 i=0;i<config->scriptList.size();i++)
{
r = config->builder.AddSectionFromFile(config->scriptList.c_str());
if( r < 0 )
{
// The builder wasn't able to load the file. Maybe the file
// has been removed, or the wrong name was given, or some
// preprocessing commands are incorrectly written.
cout<<"Error loading "<<config->scriptList<<".\n";
return;
}
//asBuildScript(config->scriptList.c_str());
}

r = config->builder.BuildModule();
if( r < 0 )
{
// An error occurred. Instruct the script writer to fix the
// compilation errors that were listed in the output stream.
cout<<"Please correct the errors in the script and try again.\n";
return;
}
return;
}


Thank you for all of the suggestions...I hope this setup works when I try to implement dynamic reloading of the scripts! More testing of that in the future!

This topic is closed to new replies.

Advertisement