Advertisement

Unable to share array<string> between AS and C++

Started by May 06, 2020 02:54 PM
2 comments, last by Elledan 4 years, 6 months ago

I'm trying to get an array<string> instance from a RegExp class I implemented on the C++ side and registered with the AS engine.

The AS side:

RegExp re;
int n = re.findall(response, matches);

Error message:

RegExp::findall(): Found -404223764 matches.
---
The script ended with an exception.
func: string getClientId()
modl:
sect: script
line: 32
desc: Index out of bounds

Method registration:

engine->RegisterObjectMethod("RegExp",
       "int findall(string &in, array<string> &inout)",
       asMETHODPR(RegExp, findall,
       (const std::string &, CScriptArray* &), int),
       asCALL_THISCALL);

Method:

int RegExp::findall(const std::string &subject, CScriptArray* &matches) {
if (!regexp) { return 0; }

Poco::RegularExpression::MatchVec matchesVector;
std::string::size_type offset = 0;
while (regexp->match(subject, offset, matchesVector)) {
 std::string substr = subject.substr(matchesVector[1].offset, matchesVector[1].length);
 matches->InsertLast(&substr);
 
 offset = matchesVector[0].offset + matchesVector[0].length;
}

int n = matches->GetSize();
std::cout << "RegExp::findall(): Found " << n << " matches." << std::endl;
return n;
}

I have tried the method registration both with &out and &inout without any difference. Trying to create a new CScriptArray object in the C++ method leads to an exception and crash to debugger.

What is the correct way to do this?

The problem is the mismatch in argument. Your function takes a reference to a pointer to the array, but you register it as a reference to the array.

I suggest you change it to the following:

int RegExp::findall(const std::string &subject, CScriptArray* matches)
{
  if (!regexp) { return 0; }

  Poco::RegularExpression::MatchVec matchesVector;
  std::string::size_type offset = 0;
  int n = 0;
  while (regexp->match(subject, offset, matchesVector)) {
    std::string substr = subject.substr(matchesVector[1].offset, matchesVector[1].length);
    if( matches ) matches->InsertLast(&substr);
    n++;
 
    offset = matchesVector[0].offset + matchesVector[0].length;
  }

  std::cout << "RegExp::findall(): Found " << n << " matches." <<  std::endl;
  return n;
}

and register it with

engine->RegisterObjectMethod("RegExp",
       "int findall(const string &in, array<string> @+ = null)",
       asMETHODPR(RegExp, findall,
       (const std::string &, CScriptArray*), int),
       asCALL_THISCALL);

I changed the argument to be by handle, registered with auto-handle so your code doesn't need to bother with the ref counting, and also modified the code to make the array optional in case the caller just want to know the number of matches but not actually the matches themselves.

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

Thank you, WitchLord, that worked splendidly ?

I hadn't used pointers before in an object method registration, hence my confusion. Perhaps a small example in the documentation for the C++ side of things could be helpful? Maybe a list of common method registration patterns?

This topic is closed to new replies.

Advertisement