Advertisement

Newbie: How do I pass a std::string to a scripted function

Started by February 04, 2016 08:30 AM
5 comments, last by WitchLord 8 years, 9 months ago

Hi

A very basic question that has had me stumped all day. First up, I'm not a c++ person, just plain C, so all the object oriented stuff is beyond me. I do have Angelscript working with my game engine, and I can call scripts from the host, and call C functions from the scripts - all working fine.

I now have a need to pass a std::string type from the host program to the script.

The script is written like this



// This function is called when a object is clicked
void as_guiHandleButtonPress(string &in objectID)
//------------------------------------------------------------
{
    sys_printConStr(objectID, "");


            if (objectID == "buttonStartGame")
            {
                currentMode = MODE_GAME;
            }}

I can create the function mapping ok - I get a valid ID back ( this from my logfile )


scriptFunctions [ void as_guiHandleButtonPress(string &in) ] has ID [ 44977616 ]

I think my problem is here - I can't work out how to pass the string as a parameter:


    if (scriptFunctions[i].param1 == true)
    {
        string testParam;
        strcpy(testParam.c_str(), funcParam);   // Convert from char to string type


        io_logToFile("Parameter to pass to script [ %s ]", testParam.c_str());
        // Has the right string "buttonStartGame"
        context->SetArgObject(0, &testParam);
    }

This is my output


Parameter to pass to script [ buttonStartGame ]
[  ] [  ]

Any advice would be welcomed.

Thanks.

The problem here is that your script function is expecting a reference to the string, i.e. "string &in objectID". Because of that you need to make sure the string that you're passing to the function stays alive through-out the execution of the script function.

Declare the testParam variable at a higher scope so you know it will stay alive long enough, and everything should work. :)

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

Advertisement


Declare the testParam variable at a higher scope so you know it will stay alive long enough, and everything should work

Thanks - tried that - still nothing. testParam is now global so should be good to go.

How can I debug a script to see if the value it actually being passed into the function?

You're copying the string into std::string's buffer incorrectly. What you're doing can result in illegal memory access and/or corrupted object state in the string object. Use assignment here:


testParam = funcParam;

You're copying the string into std::string's buffer incorrectly. What you're doing can result in illegal memory access and/or corrupted object state in the string object. Use assignment here:


testParam = funcParam;

Hah, I totally missed that.


How can I debug a script to see if the value it actually being passed into the function?

If you want to implement an interactive debugger, you can do so by building upon the Debugger add-on, or try the asPEEK third party debugger.

However, if you just want to check the value of the parameters as seen from the script, you can do so by enumerating the variables using the methods on the asIScriptContext interface, i.e. GetVarCount, GetVarName, GetAddressOfVar, etc.

You could for example, implement a simple function that prints all the local variables and their values, register it with the script engine, and then call it from the script where you wish to inspect the values.

void PrintVariables()
{
  asIScriptContext *ctx = asGetActiveContext();
  asIScriptEngine *engine = ctx->GetEngine();
 
  int typeId = ctx->GetThisTypeId();
  void *varPointer = ctx->GetThisPointer();
  if( typeId )
  {
    print(" this = 0x%x\n", varPointer);
  }
 
  int numVars = ctx->GetVarCount();
  for( int n = 0; n < numVars; n++ )
  {
    int typeId = ctx->GetVarTypeId(n); 
    void *varPointer = ctx->GetAddressOfVar(n);
    if( typeId == engine->GetTypeIdByDecl("int") )
    {
      print(" %s = %d\n", ctx->GetVarDeclaration(n, stackLevel), *(int*)varPointer);
    }
    else if( typeId == engine->GetTypeIdByDecl("string") )
    {
      std::string *str = (std::string*)varPointer;
      if( str )
        print(" %s = '%s'\n", ctx->GetVarDeclaration(n, stackLevel), str->buffer.c_str());
      else
        print(" %s = <null>\n", ctx->GetVarDeclaration(n, stackLevel));
    }
    else
    {
      print(" %s = {...}\n", ctx->GetVarDeclaration(n, stackLevel));
    }
  }
}

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

You're copying the string into std::string's buffer incorrectly. What you're doing can result in illegal memory access and/or corrupted object state in the string object. Use assignment here:


testParam = funcParam;

That was it. I thought because I was passing in a char * that it would need to be copied into std::string.c_str(). All works now.

I have also implemented the above code to display the variables as they run from the script. Only needed two small changes to work.

stackLevel wasn't declared, and this line


print(" %s = '%s'\n", ctx->GetVarDeclaration(n, stackLevel), str->buffer.c_str());

became this


print(" %s = '%s'\n", ctx->GetVarDeclaration(n, stackLevel), str->c_str());

I was getting


error: 'std::__cxx11::string {aka class std::__cxx11::basic_string<char>}' has no member named 'buffer'

Thanks for your help.

Advertisement


Only needed two small changes to work.

Sorry about that. It was a quick copy-and-paste from some test code that I have and I apparently didn't clean it up properly.

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