Argument passing behavior

Started by
5 comments, last by WitchLord 1 week, 4 days ago

Hello, I'm having a bit of trouble and hope someone can explain what I'm doing wrong.

I have a main application class registered as asOBJ_REF | asOBJ_NOCOUNT. It returns handles to various other application objects that are similarly registered. I've registered the built-in std::string with RegisterStdString().

If I print a static const string using a registered print function it's passed okay: print("static string");

If I print a string variable it passes the contents over correctly:

string msg = “string variable”;

print(msg);

However, when I pass the same variable to a member function of an application singleton it appears the string structure is (mostly) right but there are no characters in the passed string.

oEngine->RegisterObjectMethod("app", "void host_url(const string& in)", asMETHOD(_this_t, set_host_url), asCALL_THISCALL);

---

string sURL = “some url”;

app.host_url(sURL);

---

The host_url member of the application gets invoked but the passed string is empty. However, If I invoke it with a static const string it works:

---

app.host_url("http://some url");

---

When passing the string constant the characters appear correctly instantiated in the string parameter but not when passing a script string object. The characters appear missing from the string buffer though the size appears correct.

Please advise.

Many thanks.

Advertisement

Please tell me more about your C++ app implementation.

What does the class look like? Are you using any inheritance on the class? If yes, is the inheritance virtual?

What is the C++ function signature for set_host_url?

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

Hello,

struct app : std::enable_shared_from_this<app> {
	void host_url(const std::string& newval) {  _host_url = newval;  std::cout << newval << '\n'; }

	virtual void register_script_engine(typename script_engine_type::engine_ptr oEngine) {
      using namespace AngelScript;
      script_exception::throw_script_err(oEngine->RegisterObjectType("Application", 0, asOBJ_REF | asOBJ_NOCOUNT));

      script_exception::throw_script_err(oEngine->RegisterGlobalProperty("Application app", this));

      script_exception::throw_script_err(oEngine->RegisterObjectMethod("Application", "void host_url(const string& in)", asMETHOD(app, host_url), asCALL_THISCALL));
      ...
}};

— script

    string host_url = app.database().get_setting("host_url");
    
    app.host_url("urlA");
    string url = "AAA";    
    print(url);
    app.host_url(url);
    app.host_url(host_url);
    print(host_url);

The first two calls to app.host_url() work correctly. The third passes an empty string, yet it prints out the correct value from the print() command.

Passing by reference works a bit different than C++, I think that is what you are observing. This link describes it well. There is a property you can set (also in the link) to make AngelScript references behave more like C++, but it also makes the language unsafe.

david.mott said:
The first two calls to app.host_url() work correctly. The third passes an empty string, yet it prints out the correct value from the print() command.

This feels like a bug in AngelScript. I will investigate this.

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 tried to reproduce this, but everything works for me.

	{
		engine = asCreateScriptEngine();
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		bout.buffer = "";

		RegisterStdString(engine);

		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		struct app : std::enable_shared_from_this<app> {
			void host_url(const std::string& newval) { _host_url = newval; }

			virtual void register_script_engine(asIScriptEngine *oEngine) {
				oEngine->RegisterObjectType("Application", 0, asOBJ_REF | asOBJ_NOCOUNT);

				oEngine->RegisterGlobalProperty("Application app", this);

				oEngine->RegisterObjectMethod("Application", "void host_url(const string& in)", asMETHOD(app, host_url), asCALL_THISCALL);

				oEngine->RegisterObjectProperty("Application", "const string _host_url", asOFFSET(app, _host_url));
			}

			std::string _host_url;
		};

		app a;
		a.register_script_engine(engine);

		mod = engine->GetModule("test", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test",
			"void func() { \n"
			"  string host_url = 'string from db'; // app.database().get_setting('host_url'); \n"
			"  app.host_url('urlA'); \n"
			"  assert( app._host_url == 'urlA' ); \n"
			"  string url = 'AAA'; \n"
			"  app.host_url(url); \n"
			"  assert( app._host_url == 'AAA' ); \n"
			"  app.host_url(host_url); \n"
			"  assert( app._host_url == 'string from db' ); \n"
			"} \n");
		r = mod->Build();
		if (r < 0)
			TEST_FAILED;

		r = ExecuteString(engine, "func()", mod);
		if (r != asEXECUTION_FINISHED)
			TEST_FAILED;

		if (bout.buffer != "")
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		if (a._host_url != "string from db")
			TEST_FAILED;

		engine->ShutDownAndRelease();
	}

Am I missing some settings on the engine? Or perhaps some customization?

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