Jump to content
  • Advertisement
Sign in to follow this  
BlackDragon777

Newbie in AngelScripting

This topic is 4797 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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!!!!

Share this post


Link to post
Share on other sites
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 to
std::string script = LoadScript("test01.as");

engine->AddScriptSection("module", "section", script, strlen(script));
changed to
engine->AddScriptSection("module","section",script.c_str(),script.length());

const char* LoadScript(std::string scriptfile)
changed to
std::string LoadScript(const std::string& scriptfile)

return script_contents.c_str();
changed to
return script_contents;

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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!!!!

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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!!!!

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!