🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Error with stringfactory

Started by
3 comments, last by WitchLord 19 years, 8 months ago
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);
Advertisement
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 newvoid 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 );}

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

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]
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.
Please post some code.

I haven't tested Lennart's ASArray so I can't say what the problem is.

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

This topic is closed to new replies.

Advertisement