Newbie in AngelScripting

Started by
7 comments, last by Rain Dog 18 years, 10 months ago
Hi! Today I downloaded the AngelScript library and tried running a sample program. I compiled the AngelScript library as a static library. I included it into my project as well. I think I have setup all the project properties correctly. My project will compile however when I execute it, only a '0' appears on the screen. The source code that I compiled came from an earlier post. I used the guy's "corrected" code and he said it worked for him however it isn't working for me. Her is the application code.

#include <iostream>
#include <fstream>
#include "angelscript.h"
using namespace std;

const char* LoadScript(std::string scriptfile);

void Test();

int main()
{
    int counter = 0;
    
    asIScriptEngine* engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
    const char* script = LoadScript("test01.as");
	
    engine->AddScriptSection("module", "section", script, strlen(script));
    engine->RegisterGlobalProperty("int counter", &counter);
    engine->RegisterGlobalFunction("void Test()", asFUNCTION(Test), asCALL_CDECL);
    
    engine->Build("module");
    	
    asIScriptContext *context = 0;
    engine->CreateContext(&context);
    
    int functionID = engine->GetFunctionIDByDecl("module", "void DoSomething()");

    // Execute the script function
    context->Prepare(functionID);
    context->Execute();

    // Release the context when finished with it
    context->Release();
	
    // test
    cout << counter;
    cin.get();
    return EXIT_SUCCESS;
}

const char* LoadScript(std::string scriptfile)
{
    ifstream fin(scriptfile.c_str());
    char ch;
    std::string script_contents;
    
    while(fin.get(ch))
    {
       script_contents += ch;
    }
    
    fin.close();
    return script_contents.c_str();
}

void Test()
{
    cout << "Function called by script!" << endl;
}
This is the AngelScript code

void DoSomething()
{
    counter = 5;
    Test();
}
Any ideas about what I am doing wrong? Thanks again! -- Brandon Fogerty http://www.jujikasoft.com GOD Bless you Always!!!!
Advertisement
Quote: return script_contents.c_str();

This is your problem. You are returning a char pointer to a string which promptly goes out of scope and is destroyed. Try this instead.

const char* script = LoadScript("test01.as");changed tostd::string script = LoadScript("test01.as");engine->AddScriptSection("module", "section", script, strlen(script));changed toengine->AddScriptSection("module","section",script.c_str(),script.length());const char* LoadScript(std::string scriptfile)changed tostd::string LoadScript(const std::string& scriptfile)return script_contents.c_str();changed toreturn script_contents;
Deyja is correct. (Thanks for helping out, Deyja!)

If you had added some error checking you might have been able to discover this yourself.

Here are a few suggestions:

1. Always verify that the functionID is valid. Also verify the return code from Execute(). Both of these error checks would have told you that something was wrong in your program.

Execute() will return a negative value if it wasn't able to execute anything, e.g. if the context isn't prepared correctly. Otherwise it will return one of the asEXECUTION_???? codes, that you'll find in the documentation or angelscript.h.

int functionID = engine->GetFunctionIDByDecl("module", "void DoSomething()");if( functionID < 0 ){    cout << "Couldn't find the function" << endl;}else{    // Execute the script function    context->Prepare(functionID);    int r = context->Execute();    if( r != asEXECUTION_FINISHED )    {        cout << "Execution didn't finish normally. Please verify why that is. (" << r << ")" << endl;    }}


2. When registering functions and properties with the engine I always add an assert afterwards to verify the return code. I only use an assert, because if it works in debug mode, it will work in release mode as well.

r = engine->RegisterGlobalProperty("int counter", &counter); assert( r >= 0 );r = engine->RegisterGlobalFunction("void Test()", asFUNCTION(Test), asCALL_CDECL); assert( r >= 0 );


3. When calling Build() use the asIOutputStream, to receive compiler messages. Also, if the build fails, the return code will be negative, however you will catch the build error when trying to get the function ID later on so it is not necessary to check for this here.

class COutputStream : public asIOutputStream{public:    void Write(const char *text) { cout << text; }};COutputStream out;engine->Build("module", &out);


One last thing. You never release the engine in your code, causing a memory leak. Not something terribly important since the application exits anyway, but I just thought I'd point it out.

I hope you will like AngelScript, and don't hesitate to let me know if you think it can be improved in anyway. [smile]

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

Thank you Deyja. I didn't realize that until you told me. Thanks again for pointing out... my pointer. ;) However now I have another problem.
The code still compiles however when I run it I get a runtime error. So when I debug it using visual c++, it points me to AngelScript's as_array.h file.
More directly it points me to

template <class T>
T *asCArray<T>::AddressOf()
{
-> return array;
}

Here is my updated code.

#include <iostream>
#include <fstream>
#include "angelscript.h"
using namespace std;

std::string LoadScript(const std::string &scriptfile);

void Test();

int main()
{
int counter = 0;

asIScriptEngine* engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
std::string script = LoadScript("test01.as");

engine->AddScriptSection("module", "section", script.c_str(), script.length());
engine->RegisterGlobalProperty("int counter", &counter);
engine->RegisterGlobalFunction("void Test()", asFUNCTION(Test), asCALL_CDECL);

int functionID = engine->GetFunctionIDByDecl("module", "void DoSomething()");

engine->Build("module");

asIScriptContext *context = 0;
engine->CreateContext(&context);

// Execute the script function
context->Prepare(functionID);
context->Execute();

// Release the context when finished with it
context->Release();

// test
cout << counter;
cin.get();

return EXIT_SUCCESS;
}

std::string LoadScript(const std::string &scriptfile)
{
ifstream fin(scriptfile.c_str());
char ch;
std::string script_contents;

while(fin.get(ch))
{
script_contents += ch;
}

fin.close();
return script_contents;
}

void Test()
{
cout << "Function called by script!" << endl;
}

Andreas, I think I will like AngelScripting as soon as I get a demo running. =) Thanks again!

-- Brandon Fogerty
http://www.jujikasoft.com

GOD Bless you Always!!!!
You may have found a minor bug in AngelScript. I'll try to reproduce it. Do you know at what point in your program that you get the failure?

I noticed that in your new post you have changed the code to try to obtain the functionID of DoSomething() before you build the script. This will not work, in fact, my guess is that it is because of this that you get the runtime error.

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

Yes Andreas. That was the problem. I needed to put the GetFunctionID after I build the module. Thanks a lot!

-- Brandon Fogerty
http://www.jujikasoft.com

GOD Bless you Always my Friend!!!!
I don't get the runtime error when executing your application. My only guess as to the cause of that run-time error is that you might be using a different C runtime library for the AngelScript lib and your application. For example: multithreaded dll for AngelScript and singlethreaded static linking for your application. Normally you would get warning messages from the linker if that was the case.

Anyway, as your program currently is the functionID becomes -1, because you call GetFunctionIDByDecl() before you call Build(). Just changing the order of the two makes the program work as intended.

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

IIRC, if a lib is compiled as a multi-threaded DLL, it is compatible with a single-threaded app. It's when it's the other way around that it causes problems.
Well, you'll get a lot of linker errors either way. From my experience you can use /FORCE:MULTIPLE linker option to allow the linker to use whatever one it feels like and my apps have still ran.

This topic is closed to new replies.

Advertisement