Jump to content

  • Log In with Google      Sign In   
  • Create Account


- - - - -

Strings


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
9 replies to this topic

#1 Desdemona   Members   -  Reputation: 158

Like
0Likes
Like

Posted 31 August 2004 - 03:44 PM

I have a problem that is nailing me in the back. I followed Dentoid's example on using the STL string for AS. When I pass strings from the host application to script functions, everything seems to work ok. But when I start making calls between script functions using string params/return values, then all hell breaks out. This code block shows the utility script functions (called by other script functions):
string get_string(Data* pObj, string tag)
{
	string temp;
	pObj->GetAttributeBase(tag, temp);
	return temp;
}

void sendto(Data* pTarget, string text)
{ pTarget->EnqueueOutput(text); }

This block shows two versions of the same function that are called by the host application:
// This version works fine
void look_monster(Data* pPlayer, Data* pMonster)
{
	string m_name, m_desc, p_name;

	pPlayer->GetAttributeBase("name", p_name);
	pMonster->GetAttributeBase("name", m_name);
	pMonster->GetAttributeBase("desc", m_desc);

	sendto(pPlayer->GetParent(), "\x1B[0;37m" + p_name + " looks at " + m_name + ".\r\n", pPlayer);
	sendto(pPlayer, "\x1B[1;36m" + p_name + "\r\n\x1B[0;37m" + m_desc + "\r\n");
}

// This version crashes
void look_monster(Data* pPlayer, Data* pMonster)
{
	string m_name = get_string(pMonster, "name");
	string m_desc = get_string(pMonster, "desc");
	string p_name = get_string(pPlayer, "name");

	sendto(pPlayer, m_name); // Prints ok
	sendto(pPlayer, m_desc); // Prints ok
	sendto(pPlayer, p_name); // Prints garbage

//	This crashes
//	sendto(pPlayer->GetParent(), "\x1B[0;37m" + p_name + " looks at " + m_name + ".\r\n", pPlayer);
//	sendto(pPlayer, "\x1B[1;36m" + p_name + "\r\n\x1B[0;37m" + m_desc + "\r\n");
}

This is how I am setting up the string in AS.
string string_factory(asUINT length, const char *s)			{ return string(s); }
void string_ctor(string *pthis)								{ new(pthis)string(); }
void string_dtor(string *pthis)								{ pthis->~string(); }
//string& string_assign_string(string &copy, string *pthis)	{ return *new(pthis)string(copy); }
string& string_assign_string(string &copy, string *pthis)	{ return *pthis = copy; }
bool string_equal(const string &l, const string &r)			{ return l == r; }
bool string_not_equal(const string &l, const string &r)		{ return l != r; }
string string_add_string(const string &l, const string &r)	{ return l + r; }

	pEngine->RegisterObjectType("string", sizeof (string), asOBJ_IS_COMPLEX);
	pEngine->RegisterStringFactory("string", asFUNCTION(string_factory), asCALL_CDECL/* | asCALL_RETURNBYREF*/);
	pEngine->RegisterTypeBehaviour("string", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(string_ctor), asCALL_CDECL_OBJLAST);
	pEngine->RegisterTypeBehaviour("string", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(string_dtor), asCALL_CDECL_OBJLAST);
	pEngine->RegisterTypeBehaviour("string", asBEHAVE_ASSIGNMENT, "string& f(string&)", asFUNCTION(string_assign_string), asCALL_CDECL_OBJLAST);
	pEngine->RegisterTypeBehaviour(0, asBEHAVE_EQUAL, "bool f(const string&, const string&)", asFUNCTION(string_equal), asCALL_CDECL);
	pEngine->RegisterTypeBehaviour(0, asBEHAVE_NOTEQUAL, "bool f(const string&, const string&)", asFUNCTION(string_not_equal), asCALL_CDECL);
	pEngine->RegisterTypeBehaviour(0, asBEHAVE_ADD, "string f(const string&, const string&)", asFUNCTION(string_add_string), asCALL_CDECL);

I've been staring at this code for too long now and am not any closer to an answer. Any one have an idea?

Sponsor:

#2 Desdemona   Members   -  Reputation: 158

Like
0Likes
Like

Posted 31 August 2004 - 04:14 PM

Oh, one more thing:

string m_name = get_string(pMonster, "name");
string m_desc = get_string(pMonster, "desc");
string p_name = get_string(pPlayer, "name");

It is always the 3rd string that becomes gibberish, regardless of which order the calls are in.

#3 Andreas Jonsson   Moderators   -  Reputation: 3227

Like
0Likes
Like

Posted 01 September 2004 - 01:37 AM

Since it is always the third call that fails, regardless of order it is possibly a bug in AngelScript. I'll take a look at it as soon as possible.

In the meanwhile: What version of the library are you using?

You might also want to use string get_string(Data* pObj, string &tag) instead, since it would avoid passing the string object by value. It will probably not solve your problem but it is a little more efficient.



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

#4 Andreas Jonsson   Moderators   -  Reputation: 3227

Like
0Likes
Like

Posted 01 September 2004 - 06:00 AM

I found two different bugs in WIP 4 that might be related to your problem:

as_bytecode.cpp, ln 293, change to:

d.sfOffset = 0x7FFFFFFE;


as_bytecode.cpp, ln 342, change to:

if( destructors[n].sfOffset == 0x7FFFFFFE )


as_compiler.cpp, ln 1318 - 1321, change to:


{
bc->InstrWORD(BC_COPY, (short)a->type.GetSizeInMemoryDWords());
bc->Pop(1); // Pop the reference to original value
}


With these changes I can successfully run the following test case:

//
// This test shows how to register the std::string to be used in the scripts.
// It also used to verify that objects are always constructed before destructed.
//
// Author: Andreas Jönsson
//

#include "angelscript.h"
#include <stdio.h>
#include <string.h>
#include <string>
using namespace std;

#define TESTNAME "TestStdString"

class COutStream : public asIOutputStream
{
public:
void Write(const char *text) { printf(text); }
};

static string StringFactory(asUINT length, const char *s)
{
return string(s);
}

static void ConstructString(string *thisPointer)
{
new(thisPointer) string();
}

static void DestructString(string *thisPointer)
{
thisPointer->~string();
}

static string &AssignString(string &other, string &thisPointer)
{
return thisPointer = other;
}

static string ConcatenateString(string &first, string &second)
{
return first + second;
}

static string printOutput;

static void PrintString(string &str)
{
printOutput = str;
}

static const char *script2 =
"void testString() \n"
"{ \n"
" print(getString(\"Ida\")); \n"
"} \n"
" \n"
"string getString(string &str) \n"
"{ \n"
" return \"hello \" + str; \n"
"} \n";


bool TestStdString()
{
bool fail = false;

asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

engine->RegisterObjectType ("string", sizeof(string), asOBJ_CLASS_CDA);
engine->RegisterStringFactory ("string", asFUNCTION(StringFactory), asCALL_CDECL);
engine->RegisterObjectBehaviour ("string", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructString), asCALL_CDECL_OBJLAST);
engine->RegisterObjectBehaviour ("string", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(DestructString), asCALL_CDECL_OBJLAST);
engine->RegisterObjectBehaviour ("string", asBEHAVE_ASSIGNMENT, "string &f(const string&)", asFUNCTION(AssignString), asCALL_CDECL_OBJLAST);
engine->RegisterObjectBehaviour (0, asBEHAVE_ADD, "string f(const string&, const string &)", asFUNCTION(ConcatenateString), asCALL_CDECL);
engine->RegisterGlobalFunction("void print(string &)", asFUNCTION(PrintString), asCALL_CDECL);

COutStream out;


engine->AddScriptSection(0, TESTNAME, script2, strlen(script2), 0);
engine->Build(0, &out);

engine->ExecuteString(0, "testString()", &out, 0);

if( printOutput != "hello Ida" )
{
fail = true;
printf("%s: Failed to print the correct string\n", TESTNAME);
}

engine->Release();

return fail;
}





You're probably running version 1.8.2, right? I'll verify if the same bugs exists in that version and let you know how to fix them.



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

#5 Desdemona   Members   -  Reputation: 158

Like
0Likes
Like

Posted 01 September 2004 - 06:50 AM

I'm using 1.8.1 at the moment (last official release when I started my project). I'm to a point in my project that it wont be any hassle to start trying out the WIPs, so I'll upgrade to the latest one.

Thanks for the response. Going to lunch now but I'll check your suggestions when I get back

#6 Desdemona   Members   -  Reputation: 158

Like
0Likes
Like

Posted 01 September 2004 - 10:24 AM

I tried changing "get_string(Data* pData, string tag)" to "get_string(Data* pData, string& tag)" but that didnt work. For example, if I have a statement like "string p_name = get_string(pPlayer, "name")", then AS will call the function ok. But afterwards, any attempt to use p_name will cause AS to quiety abort out of the function.

I download WIP4 and applied the changes you suggested, but AS is refusing to compile my script code:


Code.as (514, 7) : Error : Expected '('
Code.as (517, 2) : Error : Expected expression value
Code.as (521, 38) : Error : Expected expression value
Code.as (526, 2) : Error : Expected expression value
Code.as (531, 2) : Error : Expected expression value
Code.as (536, 2) : Error : Expected expression value
Code.as (541, 2) : Error : Expected expression value
Code.as (546, 2) : Error : Expected expression value
Code.as (551, 2) : Error : Expected expression value
Code.as (556, 2) : Error : Expected expression value
Code.as (561, 2) : Error : Expected expression value
Code.as (566, 2) : Error : Expected expression value



I am assuming the line numbers relate to the code below are correct. I only have one script file and I added the section at line offset 0.


511 void show_move(Data* pPlayer, Data* pDst, Data* pSrc)
512 {
513 uint temp = 0;
514 uint from = 0;
515 string name, to_src, to_dst;
516
517 from = pSrc->GetId();
518
519 pPlayer->GetAttributeBase("name", name);
520
521 if (pDst->GetRefid("east", temp) && from == temp)
// ...



I'm still looking into this problem at the moment, but yeah, it doesn't make a lot of sense.

#7 Desdemona   Members   -  Reputation: 158

Like
0Likes
Like

Posted 01 September 2004 - 10:37 AM

At the moment it seems that if functions that have 2 or more uints declared are causing the problems. If I remove one of the uints from the function it compiles ok.

Also, the declaration "uint temp, from" results in "Code.as (590, 13) : Error : Expected identifier"


#8 Andreas Jonsson   Moderators   -  Reputation: 3227

Like
0Likes
Like

Posted 01 September 2004 - 02:35 PM

"from" is a reserved keyword in 1.9.0, as is "import". This is why you're getting these errors.

They are used by the new global statement:

import void function_decl(int param1, int param2) from "module";

I've yet to come up with a good solution for allowing the use of these keywords in other contexts, e.g. variable names.

You could temporarily rename the keywords by changing the as_tokendef.h file.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

#9 Desdemona   Members   -  Reputation: 158

Like
0Likes
Like

Posted 01 September 2004 - 04:59 PM

Oh man... Its nice when things are not serious, but damn.. I feel like a dork!

#10 Andreas Jonsson   Moderators   -  Reputation: 3227

Like
0Likes
Like

Posted 02 September 2004 - 01:42 AM

No worries. [smile]

I believe I've figured out a way to avoid making 'from' a reserved keyword. I'll try to incorporate it into WIP 5.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS