Sign in to follow this  
Rain Dog

Error with stringfactory

Recommended Posts

i have the following script
int sum1(int a, int b)
{
	return a+b;
}

void main()
{
	CString h = "h";
	for (int i = 0; i < 10; i++)
	{
		sum +=sum1(sum,i);
		//m_PlayerStatus = sum;
		//UpdateData(0);
	}
}
Whenever i make a string, my length and char* pointers that are passted to my registered stringfactory function are wrong. I get passed a length of 13294820 and a badptr for my char* Here are my functions and the code to register them.
CString StringFactory (asUINT length, const char *s)
{
	CString tmp;
	tmp.Format(_T("%s"), s);
    return tmp;
} 
void ConstructString (CString *thisPointer)
{
    thisPointer = new CString();
}
void DestructString (CString *thisPointer)
{
    thisPointer->~CString ();
}

void AssignString (CString &other, CString *thisPointer)
{
    thisPointer = new CString(other);
}

	ASEngine->RegisterObjectType ("CString", sizeof (CString), asOBJ_CLASS);
    ASEngine->RegisterStringFactory ("CString", asFUNCTION(StringFactory), asCALL_CDECL);
    ASEngine->RegisterObjectBehaviour ("CString", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructString), asCALL_CDECL_OBJLAST);
    ASEngine->RegisterObjectBehaviour ("CString", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(DestructString), asCALL_CDECL_OBJLAST);
    ASEngine->RegisterObjectBehaviour ("CString", asBEHAVE_ASSIGNMENT, "CString &f(const CString&)", asFUNCTION(AssignString), asCALL_CDECL_OBJLAST);

Share this post


Link to post
Share on other sites
The problem lies with how you registered the CString type. I'm betting that your CString C++ class has a constructor, a destructor, and maybe even an overloaded assignment operator. If that is so you need to register the type with the asOBJ_CLASS_CDA flag. This flag is actually a shortcut for asOBJ_CLASS | asOBJ_CLASS_CONSTRUCTOR | asOBJ_CLASS_DESTRUCTOR | asOBJ_CLASS_ASSIGNMENT.

What is happening is that your StringFactory function is expecting a hidden pointer to be passed to it before the length parameter. This pointer holds the location where the returned CString should be initialized. But since you didn't register the CString type with asOBJ_CLASS_CDA AngelScript has no way of knowing that your C++ function wants that hidden pointer. You can verify this situation by converting the length parameter to char *, you'll see that it is actually the pointer to the string buffer.

I'll make a note in the manual about this very common mistake.

If only there where some way of autodetecting the correct flag to use when registering a type.

Your ConstructString() function is wrong. It should be:


#include <new.h> // Include placement new

void ConstructString(CString &self)
{
new(&self) CString;
}


Your AssignString() function is also wrong. It should be:


CString &AssignString(CString &other, CString &self)
{
return self = other;
}


It would also be possible to register the overloaded assignment operator directly using asCALL_THISCALL.

The following code shows how to register std::string for use with AngelScript. I'm sure you can adapt this for your CString class.

[AngelScript 1.10.0 WIP 4]


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

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();
}

void RegisterStdString(asIScriptEngine *engine)
{
int r;

// Register the bstr type
r = engine->RegisterObjectType("string", sizeof(string), asOBJ_CLASS_CDA); assert( r >= 0 );

// Register the bstr factory
r = engine->RegisterStringFactory("string", asFUNCTION(StringFactory), asCALL_CDECL); assert( r >= 0 );

// Register the object operator overloads
r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("string", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(DestructString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("string", asBEHAVE_ASSIGNMENT, "string &f(const string &)", asMETHODPR(string, operator =, (const string&), string&), asCALL_THISCALL); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("string", asBEHAVE_ADD_ASSIGN, "string &f(const string &)", asMETHODPR(string, operator+=, (const string&), string&), asCALL_THISCALL); assert( r >= 0 );

// Register the global operator overloads
r = engine->RegisterGlobalBehaviour(asBEHAVE_EQUAL, "bool f(const string &, const string &)", asFUNCTIONPR(operator==, (const string &, const string &), bool), asCALL_CDECL); assert( r >= 0 );
r = engine->RegisterGlobalBehaviour(asBEHAVE_NOTEQUAL, "bool f(const string &, const string &)", asFUNCTIONPR(operator!=, (const string &, const string &), bool), asCALL_CDECL); assert( r >= 0 );
r = engine->RegisterGlobalBehaviour(asBEHAVE_LEQUAL, "bool f(const string &, const string &)", asFUNCTIONPR(operator<=, (const string &, const string &), bool), asCALL_CDECL); assert( r >= 0 );
r = engine->RegisterGlobalBehaviour(asBEHAVE_GEQUAL, "bool f(const string &, const string &)", asFUNCTIONPR(operator>=, (const string &, const string &), bool), asCALL_CDECL); assert( r >= 0 );
r = engine->RegisterGlobalBehaviour(asBEHAVE_LESSTHAN, "bool f(const string &, const string &)", asFUNCTIONPR(operator <, (const string &, const string &), bool), asCALL_CDECL); assert( r >= 0 );
r = engine->RegisterGlobalBehaviour(asBEHAVE_GREATERTHAN, "bool f(const string &, const string &)", asFUNCTIONPR(operator >, (const string &, const string &), bool), asCALL_CDECL); assert( r >= 0 );
r = engine->RegisterGlobalBehaviour(asBEHAVE_ADD, "string f(const string &, const string &)", asFUNCTIONPR(operator +, (const string &, const string &), string), asCALL_CDECL); assert( r >= 0 );

// Register the object methods
r = engine->RegisterObjectMethod("string", "uint length()", asMETHOD(string,size), asCALL_THISCALL); assert( r >= 0 );
}


Share this post


Link to post
Share on other sites
I get the following errors with your code, and i have had similar errors with different functions and was wondering how i would resolve them:


error C2440: 'type cast' : cannot convert from 'overloaded-function' to 'bool (__cdecl *)(const std::string &,const std::string &)'


with these lines of code:

r = engine->RegisterGlobalBehaviour(asBEHAVE_EQUAL, "bool f(const string &, const string &)", asFUNCTIONPR(operator==, (const string &, const string &), bool), asCALL_CDECL); assert( r >= 0 );
r = engine->RegisterGlobalBehaviour(asBEHAVE_NOTEQUAL, "bool f(const string &, const string &)", asFUNCTIONPR(operator!=, (const string &, const string &), bool), asCALL_CDECL); assert( r >= 0 );



Also, if i omit those, i can succesfully compile a script, but if i try to use the registered string in my script, i crash. I have pinpointed the crash to the assignment of a string.

this is the code i use:


void main()
{
string s = "hello";
}


I use the exact functions that you listed above.

[Edited by - Rain Dog on October 17, 2004 11:46:25 PM]

Share this post


Link to post
Share on other sites
I have the above problem solved now.

Turns out, all i had to do was remove the
r = engine->RegisterObjectBehaviour(0, asBEHAVE_ASSIGNMENT, "string &f(string&, const string &)", asFUNCTION(AssignString), asCALL_CDECL); assert( r >= 0 );

registration and it works fine now, oh and I had to write and my own functions for == and !=

But i am having now a problem with Lennart Denninger's asarray templated array implementation.

There are problemns with the following:

static void _cdecl ASConstruct(ASArray<T> & inThis);

is called in the implementation and is passed a T instead of an ASArray<T>&

also in the same function, ASConstruct is referenced like this: T::ASConstruct(...)

Which gives me namespace resolution errors.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this