Jump to content

  • Log In with Google      Sign In   
  • Create Account


Heuristics

Member Since 23 Sep 2012
Offline Last Active May 14 2013 07:41 AM

Topics I've Started

Returning text crashes as with Mingw 4.71 but not with 4.4.1

28 March 2013 - 03:02 AM

The following is a short summary of the code that crashes angelscript in 4.7.1 but not in 4.4.1:

 

struct A {
    A() {}
    static void Constructor(A *self) {new(self) A();}
    static void Destructor(A *memory) {memory->~A();}
    std::string getText() {return this->text;}
    std::string text;
    A getA() {return A();}
};

____Code run in Angelscript____:
void main() {
    A a;
    string text = a.getA().getText();
}

 

I have appended a full runnable example below since it might just be that I am registering things in the wrong way (lets hope so).

It appears to be the case that running a function that returns text from an object that was created within angelscript causes a crash.

 


#include <angelscript.h>
#include <add_on/scriptstdstring/scriptstdstring.h>
#include <add_on/scriptbuilder/scriptbuilder.h>
#include <stdio.h>
#include <assert.h>
#include <iostream>

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(const std::string &in) {
    std::cout << in << std::endl;
}

struct A {
    A() {}
    static void Constructor(A *self) {new(self) A();}
    static void Destructor(A *memory) {memory->~A();}
    std::string getText() {return this->text;}
    std::string text;
    A getA() {return A();}
};

void registerA(asIScriptEngine *engine) {
    std::string name = "A";
    int r = engine->RegisterObjectType(name.c_str(), sizeof(A), asOBJ_VALUE | asOBJ_APP_CLASS | asOBJ_APP_CLASS_CONSTRUCTOR); assert( r >= 0 );
    r = engine->RegisterObjectBehaviour(name.c_str(), asBEHAVE_CONSTRUCT, std::string("void f()").c_str(), asFUNCTION(A::Constructor), asCALL_CDECL_OBJLAST); assert( r >= 0 );
    r = engine->RegisterObjectBehaviour(name.c_str(), asBEHAVE_DESTRUCT, "void f()", asFUNCTION(A::Destructor), asCALL_CDECL_OBJLAST); assert( r >= 0 );
    r = engine->RegisterObjectMethod("A", "string getText()", asMETHOD(A,getText), asCALL_THISCALL);assert( r >= 0 );
    r = engine->RegisterObjectMethod("A", "A getA()", asMETHOD(A,getA), asCALL_THISCALL);assert( r >= 0 );
}

std::string app = "void main() {A a;string text = a.getA().getText();}";

int main() {
    asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
    int r = engine->SetMessageCallback(asFUNCTION(MessageCallback), 0, asCALL_CDECL); assert( r >= 0 );
    RegisterStdString(engine);
    r = engine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(print), asCALL_CDECL); assert( r >= 0 );

    registerA(engine);

    CScriptBuilder builder;
    r = builder.StartNewModule(engine, "MyModule"); if( r < 0 ) {printf("Unrecoverable error while starting a new module.\n");return 0;}
    r = builder.AddSectionFromMemory("TestSection", app.c_str());if( r < 0 ) {printf("Please correct the errors in the script and try again.\n");return 0;}
    r = builder.BuildModule(); if( r < 0 ) {printf("Please correct the errors in the script and try again.\n");return 0;}

    asIScriptModule *mod = engine->GetModule("MyModule");
    asIScriptFunction *func = mod->GetFunctionByDecl("void main()"); if( func == 0 ) {printf("The script must have the function 'void main()'. Please add it and try again.\n");return 0;}
    asIScriptContext *ctx = engine->CreateContext();
    ctx->Prepare(func);
    r = ctx->Execute(); if( r != asEXECUTION_FINISHED and r == asEXECUTION_EXCEPTION) {printf("An exception '%s' occurred. Please correct the code and try again.\n", ctx->GetExceptionString());}
}

 

 


This changes when returning value objects

11 March 2013 - 02:41 AM

compiler: mingw 4.7.2

os: Windows 7

angelscript: official 2.26.1

 

I have a problem that I cannot solve, I am hoping that I am just registering something wrong.

 

The short story of the symptoms:

----------------------

When registering a struct as a value type the value of 'this' changes by a few bytes if a called member function of that struct is returning another registered struct value type, 'this' does not change when returning nothing (void) or when returning float.

 

This bug goes away if at least 3 int (for example) member variables are added to the registered value struct that is returned, if so then 'this' does not change.

----------------------

 

Here is a small example that illustrates the problem.

 

We have 2 structs (Dummy and Test) and we register them in angelscript. 'Test' has a debug printing of 'this' at every function that gets run from it. We then run these lines in angelscript:

void main() {
    Test test;
    test.noReturnValue();
    test.floatReturnValue();
    test.getDummy();
}

 

 

This run outputs:

 

Constructor self address: 0x60e7c4
This print from constructor: 0x60e7c4
This print from noReturnValue function: 0x60e7c4
This print from floatReturnValue function: 0x60e7c4
This print from getDummy function: 0x60e7bc

The application also crashes at the end of the run.

 

The last lines shows that 'this' changes slightly due to that function call returning a 'Dummy' value.

 

Here is an example program that is as small as I could make it that still shows the problem (this is c++11 code).

 

 

 

#include <angelscript.h>
#include <add_on/scriptstdstring/scriptstdstring.h>
#include <add_on/scriptbuilder/scriptbuilder.h>
#include <stdio.h>
#include <assert.h>
#include <iostream>

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(const std::string &in) {
    std::cout << in << std::endl;
}

struct Dummy {
    static void Constructor(Dummy *self) {new(self) Dummy();}
    static void Destructor(Dummy *memory) {memory->~Dummy();}
    //int a, b, c; // uncomment this line for it to work again
    //int a, b; // will not work, requires at least 3 extra vars
};

struct Test {
    Test() {
        std::cout << "This print from constructor: " << this << std::endl;
    }
    static void Constructor(Test *self) {std::cout << "Constructor self address: " << self << std::endl;new(self) Test();}
    static void Destructor(Test *memory) {memory->~Test();}
    void noReturnValue() {
        std::cout << "This print from noReturnValue function: " << this << std::endl;
    }
    float floatReturnValue() {
        std::cout << "This print from floatReturnValue function: " << this << std::endl;
        return 5.6;
    }
    Dummy getDummy() {
        std::cout << "This print from getDummy function: " << this << std::endl;
        return Dummy();
    }
};

template<typename T>
void reg(asIScriptEngine *engine, std::string name) {
    int r = engine->RegisterObjectType(name.c_str(), sizeof(T), asOBJ_VALUE | asOBJ_APP_CLASS_CDAK ); assert( r >= 0 );
    r = engine->RegisterObjectBehaviour(name.c_str(), asBEHAVE_CONSTRUCT, std::string("void f()").c_str(), asFUNCTION(T::Constructor), asCALL_CDECL_OBJLAST); assert( r >= 0 );
    r = engine->RegisterObjectBehaviour(name.c_str(), asBEHAVE_DESTRUCT, "void f()", asFUNCTION(T::Destructor), asCALL_CDECL_OBJLAST); assert( r >= 0 );
}

std::string app = R"(void main() {
    Test test;
    test.noReturnValue();
    test.floatReturnValue();
    test.getDummy();
})";

int main() {
    asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
    int r = engine->SetMessageCallback(asFUNCTION(MessageCallback), 0, asCALL_CDECL); assert( r >= 0 );
    RegisterStdString(engine);
    r = engine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(print), asCALL_CDECL); assert( r >= 0 );

    reg<Dummy>(engine, "Dummy");
    reg<Test>(engine, "Test");
    r = engine->RegisterObjectMethod("Test", "Dummy getDummy()", asMETHOD(Test,getDummy), asCALL_THISCALL);assert( r >= 0 );
    r = engine->RegisterObjectMethod("Test", "void noReturnValue()", asMETHOD(Test,noReturnValue), asCALL_THISCALL);assert( r >= 0 );
    r = engine->RegisterObjectMethod("Test", "float floatReturnValue()", asMETHOD(Test,floatReturnValue), asCALL_THISCALL);assert( r >= 0 );

    CScriptBuilder builder;
    r = builder.StartNewModule(engine, "MyModule"); if( r < 0 ) {printf("Unrecoverable error while starting a new module.\n");return 0;}
    r = builder.AddSectionFromMemory("TestSection", app.c_str());if( r < 0 ) {printf("Please correct the errors in the script and try again.\n");return 0;}
    r = builder.BuildModule(); if( r < 0 ) {printf("Please correct the errors in the script and try again.\n");return 0;}

    asIScriptModule *mod = engine->GetModule("MyModule");
    asIScriptFunction *func = mod->GetFunctionByDecl("void main()"); if( func == 0 ) {printf("The script must have the function 'void main()'. Please add it and try again.\n");return 0;}
    asIScriptContext *ctx = engine->CreateContext();
    ctx->Prepare(func);
    r = ctx->Execute(); if( r != asEXECUTION_FINISHED and r == asEXECUTION_EXCEPTION) {printf("An exception '%s' occurred. Please correct the code and try again.\n", ctx->GetExceptionString());}
}

 

 

 


Function parameter problem

23 September 2012 - 01:17 AM

Hello!

I am new to angelscript and I have a problem where the first parameter to a registered object method is always the object itself. What can I do to fix this? Here is some example code:

[source lang="cpp"]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);}[/source]

[source lang="cpp"]class Person { public: Person() {} void printTwoInts(int a, int b); void AddRef() {} void ReleaseRef() {} static Person *refFactory() { return new Person(); };};Person::printTwoInts(int a, int b){ cout (int)this " " a " " b endl;}(had to remove left arrows for cout in the above code above)[/source]

[source lang="cpp"]int main() { asIScriptEngine *scriptEngine = asCreateScriptEngine(ANGELSCRIPT_VERSION); int r = scriptEngine->SetMessageCallback(asFUNCTION(MessageCallback_), 0, asCALL_CDECL);assert( r >= 0 ); r = scriptEngine->RegisterObjectType("Person", sizeof(Person), asOBJ_REF); assert( r >= 0 ); r = scriptEngine->RegisterObjectBehaviour("Person", asBEHAVE_FACTORY, "Person @f()", asFUNCTION(Person::refFactory), asCALL_CDECL); assert( r >= 0 ); r = scriptEngine->RegisterObjectBehaviour("Person", asBEHAVE_ADDREF, "void f()", asMETHOD(Person, AddRef), asCALL_THISCALL); assert( r >= 0 ); r = scriptEngine->RegisterObjectBehaviour("Person", asBEHAVE_RELEASE, "void f()", asMETHOD(Person, ReleaseRef), asCALL_THISCALL); assert( r >= 0 ); r = scriptEngine->RegisterObjectMethod("Person", "void printTwoInts(int a, int b)", asMETHOD(Person, printTwoInts), asCALL_THISCALL);assert( r >= 0 ); CScriptBuilder builder; r = builder.StartNewModule(scriptEngine, "Test"); assert( r >= 0 ); r = builder.AddSectionFromFile("./Test.as"); assert( r >= 0 ); r = builder.BuildModule();if( r < 0 ); assert( r >= 0 ); asIScriptModule *mod = scriptEngine->GetModule("Test"); asIScriptFunction *func = mod->GetFunctionByDecl("void main()"); asIScriptContext *ctx = scriptEngine->CreateContext(); ctx->Prepare(func); r = ctx->Execute(); return 0;}[/source]


The Test.as script is as:

[source lang="cpp"]void main() { Person p; p.printTwoInts(999,55);}[/source]


When run this outputs: "8097752 8097752 999" Meaning the first parameter is not an int but an object pointer. So the function calling is done wrong? But when I try to change asCALL_THISCALL to asCALL_CDECL, asCALL_STDCALL, asCALL_CDECL_OBJLAST, asCALL_CDECL_OBJFIRST or asCALL_GENERIC I get an error code: -24. -24 is asWRONG_CALLING_CONV but I don't know how to fix that. Do I need to use something else other then asMETHOD when registering the function? If so what?

I am using mingw 4.7.0.

Thanks.

PARTNERS