Advertisement

Struggling to understand how to use references

Started by December 21, 2016 03:04 AM
2 comments, last by calzone 7 years, 10 months ago

I'm struggling to understand how to use the ref add-on both in script and across the script/c++ interface.

I understand the basics of pointers but am having a hard time wrapping my head around how angelscript interfaces with c++ for function calls.

Problem one: error when using refs with string.

script code


string str1;
string str2;
ref @strref1;
	
str1 = "hello world";
	
@strref1 = str1;
	
print(str1);
	
str6 = cast<string>(strref1);

When compiling the script, this returns: ERR : Illegal target type for reference cast.

Why can't a ref be case to to a string?

Problem two: problems passing refs to c++

declared a function:


//C++
void test_pass_ref(CScriptHandle *&arg){
	void *ptr;
	
	ptr = arg->GetRef();
	cout << "ptr is " << ptr << endl;
	cout<< "str passed is " << static_cast <char*> (ptr) << endl;
	cout<< "exit"<<endl;
}

//registered like this
r = engine->RegisterGlobalFunction("void test_pass_ref(ref@ &in)", asFUNCTION(test_pass_ref), asCALL_CDECL);

Attempting to use it like this in a script


string str5;
ref @strref1;

str5 = "hello world";
@strref1 = str5;
test_pass_ref(strref1);

Get the following output:

ptr is 0
str passed is Segmentation fault

Why does GetRef() not return the pointer of the string? Any help in understanding would be appreciated.

As stated by its documentation, the ref type "can refer to any object type (as long as it is a reference type)". However, the string type is registered as a value type. The distinction between a value type and a reference type is somewhat important in all of AngelScript, as value types don't support handles (@) or inout references (&), which, deeper down, is because they don't register garbage collection/reference counting mechanisms, thus making it unsafe to store any references to them other than the object itself. With some effort, it's possible to register string as a reference type, although consider whether the purposes you need it for are worth it.

The second problem you're experiencing is, first off, because the ref type can't hold references to strings, as explained earlier. If it were to occur for other types, make sure you're using an AngelScript version that incorporates revision 2347, such as the latest stable release (2.31.2). If updating the library version your project uses is not viable, or just if you'd rather have reasonable code, change the AngelScript function signature to "void test_pass_ref(ref@)" and the C++ one to "void test_pass_ref(CScriptHandle *arg)". There is no reason to ever use "@ &in" in AngelScript. And regardless of all that, if assigning it to the reference and passing it to the function actually worked, I guarantee that casting what's internally an std::string* to char* and printing that, wouldn't do anybody any good.

Advertisement

Thanks for your response and help. Another read-through of the documentation would probably do me some good.

I'll re-do this test with a different class and see if I still have issues.

For those curious, i was able to get this to work with handles, refs, and a custom class "Person":

C++ function declarations:


void GetPersonObject(Person &p1);
void GetPersonHandle(Person *&ptr);
void GetRefToPerson(CScriptHandle *h1);

registered as:


RegisterGlobalFunction("void GetPersonObject(Person &)", asFUNCTION(GetPersonObject), asCALL_CDECL);
RegisterGlobalFunction("void GetPersonHandle(Person@ &out)", asFUNCTION(GetPersonHandle), asCALL_CDECL);
RegisterGlobalFunction("void GetRefToPerson(ref@)", asFUNCTION(GetRefToPerson), asCALL_CDECL);

Used in script as follows:


Person a;    
GetPersonObject(a);    
Person@ b;    
GetPersonHandle(@b);
ref @r1;
@r1 = a;
GetRefToPerson(r1);

where


void GetRefToPerson(CScriptHandle *h1)
{
    int type_id;
    Person *pp1;
    void *ptr = operator new(8);
    
    type_id = h1->GetTypeId();
    h1->Cast(&ptr,type_id);
    
    if(ptr != NULL)
    {
        //determined it's of type person
        pp1 = static_cast<Person*>(h1->GetRef());        
        cout<<"name of person is: "<<p1->name<<endl;
    }
}

Thanks again, Sir Ementaler

This topic is closed to new replies.

Advertisement