Binding std::string operators in AngelScript

Started by
7 comments, last by Deyja 19 years, 8 months ago
I'm trying to bind some binary operators in AngelScript. The operators are == and +, on std::string. I'm not quite sure if I've set them up right. These binary operators shouldn't have this pointers, so I tried them that way first. I tried them with this pointers, and they still don't work. Simply registering these behaviors - wether I use them or not - makes building fail. Here is my binding code:

std::string CreateString(asUINT length, const char * str)
{
	return std::string(str);
}

void ConstructString(std::string* str)
{
	new (str) std::string();
}

void DestructString(std::string* str)
{
	str->~basic_string();
}

std::string& AssignString(const std::string& src, std::string* dest)
{
	*dest = src;
	return *dest;
}

std::string AddString(const std::string& rhs, std::string* thisp)
{
	return (*thisp)+rhs;
}

std::string& AddAssignString(const std::string& rhs, std::string* thisp)
{
	*thisp += rhs;
	return *thisp;
}

bool CompareStlString(const std::string& rhs, std::string* thisp)
{
	return rhs == (*thisp);
}

void BindStlString(asIScriptEngine* engine)
{
	engine->RegisterObjectType ("string", sizeof (std::string), asOBJ_CLASS_CDA);
    engine->RegisterStringFactory ("string", asFUNCTION(CreateString), 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 ("string", asBEHAVE_ADD, "string f(const string&)", asFUNCTION(AddString), asCALL_CDECL_OBJLAST);
	engine->RegisterObjectBehaviour ("string", asBEHAVE_ADD_ASSIGN, "string& f(const string&)", asFUNCTION(AddAssignString), asCALL_CDECL_OBJLAST);
	engine->RegisterObjectBehaviour ("string", asBEHAVE_EQUAL, "bool f(const string&)", asFUNCTION(CompareStlString), asCALL_CDECL_OBJLAST);
}

And my test script

//String test

void Test()
{
	string one = "Hello ";
	string two = "world";
	string three = "!";
	one += two;
	if (three == "!") Print(one+three);
}

Also; I've never seen 'behavior' spelled with a u before. Is it a British spelling?
Advertisement
The add and compare behaviours are binary operators, and shouldn't be registered as methods. A future version of AngelScript might allow them to be registered as methods, but not yet.

std::string AddString(const std::string &lft, const std::string &rgt){  return lft+rgt;}std::string CompareString(const std::string &lft, const std::string &rgt){  return lft==rgt;}r = engine->RegisterObjectBehaviour(0, asBEHAVE_ADD, "string f(const string&, const string&)", asFUNCTION(AddString), asCALL_CDECL); assert( r >= 0 );r = engine->RegisterObjectBehaviour(0, asBEHAVE_COMPARE, "string f(const string&, const string&)", asFUNCTION(CompareString), asCALL_CDECL); assert( r >= 0 );


The rest is correct, at least as far as I can see without actually testing the code.

If you check the return code for each of the Register functions (e.g. like I show above) you would know which one caused the problem.

Yes, behaviour is british spelling. [wink]

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 was able to confirm that it was the binary functions causing the problem simply because commenting them out made the script build - of course, then it gave me errors, when before it had failed silently.

I can see now how RegisterObjectBehavior can get all the information it needs from the function signature - and how it even allows mixing types, but it seems a little odd at first to register an object behavior without specifying a type.

I keep spelling Behavior 'right', and I don't notice it until the compiler yells at me.
Thank you, it works wonderfully now. The script prints Hello World!, just as it should! Now I can begin implementing more advanced string-handling functions.

I do have one concern. Does AngelScript follow the same overload-matching rules as C++? Does it support different return types for overloads? I'm going to be binding several functions for converting basic types to and from string, and would like to give them a common name and let the return type and the conversion function to be called be determined by the function overload system. It's not templates, but it sure kicks a bunch of ****ToString(...) functions in the pants!

I was very happy when I stumbled across AngelScript. I couldn't believe I'd missed it before! I'd been mucking about trying to get LUA to do what I wanted for a long time, and AngelScript does it all already. I'm currently working on a Mud engine that uses script for all it's content, and that means a great deal of string parsing. Hopefully, I'll be able to move all command-processing into script, and just use the command entered to generate the name of a function to call, much like I did in LUA.
Quote:Original post by WitchLord
The add and compare behaviours are binary operators, and shouldn't be registered as methods. A future version of AngelScript might allow them to be registered as methods, but not yet.


By the way, data type ("vector") is specified in the example from your site

Quote:
engine->RegisterObjectBehaviour("vector", asBEHAVE_ADD, "vector f(vector &, vector &)", asFUNCTIONP(operator+, (CVector &, CVector &)), asCALL_CDECL);


But if you try to actually register a function like this, DetectCallingConvention() won't allow asCALL_CDECL here (which seems to be logical). Either I'm doing something wrong or the example is misguiding ;)

And IMHO it is not convenient that C++ and AngelScript function signatures differ for asCALL_CDECL_OBJLAST methods.

Cheers,
RCL
Deyja:

I agree that allowing registration of both object behaviours and operator overloads with the same method can be a bit confusing. I'll probably separate the two functionalities to fix this.

I try to follow the same overloading rules as C++, which means that functions that have different parameters can use the same name, but if only the return type differs they can use the same name. If you find that AngelScript doesn't do this correctly, let me know so that I can fix it.

I'm very pleased to know that you like AngelScript. Let me know if there is anything I can do to improve it even more.

RCL:

The example must be wrong. I haven't actually tried it, I just uploaded what Lennart sent me (and he was using an older version). I'll correct it as soon as possible.

asCALL_CDECL_OBJLAST is a substitute for asCALL_THISCALL, it was included for those cases where an object method didn't exist or couldn't be written. The AngelScript function signature don't include the object pointer because it is sent hiddenly. I'm including asCALL_CDECL_OBJFIRST as well with the next version, to give one more option for developers.

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

A preprocessor would be nice, but don't worry about it - I'm already writing one. I have includes working, and all the framework I need to implement defines. It's rather inefficient though. In order the handle defines, I have to break the script down into it's constituent tokens. Then I have to put it back together, and hand it off to AngelScript - which just does it all over again. My lexer was also written for a different purpose, but has been curelly bent to the task of lexing C code.

I think the only thing keeping AngelScript from implementing a pre-processor itself is that it does not load files itself, so it has no way of handling #include. I'll post it on here once I have #define working, though it's going to drag a bit of baggage with it.
I don't have any plans of adding a preprocessor to the main library of AngelScript at this point. But an external preprocessor would be an excellent add-on. Maybe in the future once AngelScript is more mature I'll consider an internal preprocessor.

I look forward to adding your preprocessor to the AngelScript add-ons on the site.

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

Well. Good luck with it. :D Included in this zip is the preprocessor and all the support code for running the test-script. Theres a compiled angelscript.lib included, just in case my code is not compatible with any changes you've made since your last release.

http://www.omnisu.com/preprocessor.zip

The preprocessor supports #include, and protects against multiple-inclusion.
It supports #define, but not function-defines. That is, #define PRINTHW Print("Hello World!"); is fine, but #define PRINTSOMESTUFF(a,b) Print(a); Print(b); is not supported yet.
Those kind of macros will probably come after #ifdef, #ifndef, and #endif.

This topic is closed to new replies.

Advertisement