Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: Error message returning a TStringList



Permlink Replies: 2 - Last Post: Jan 31, 2018 2:35 AM Last Post By: Patricio Cerda Threads: [ Previous | Next ]
Patricio Cerda

Posts: 122
Registered: 3/13/01
Error message returning a TStringList
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 29, 2018 9:47 AM
Hi,

I'm working with C++Builder Berlin 10.1 and trying to define a method on the server side of my DataSnap server, where I must to return a TStringList, but the compiler show me the following error message: "Delphi style classes must be constructed using operator new" and also shows in red color the last line of the .cpp code).

This is my .cpp code:
TStringList TDSSM_VentasAlahora::ObtieneListaFolioAsignadoVendedor(int IdVendedor, int TipoFolio)
{
	String QueryListaFolios = "select NumeroFolio from FoliosContratos where IdVendedor = " + String(IdVendedor) + " and IdTipoContrato = " + String(TipoFolio) + " and IdEstado = 2 order by Id asc";
	SQLQ_Aux->Active = false;
	SQLQ_Aux->SQL->Text = QueryListaFolios;
	SQLQ_Aux->Active = true;
	SQLQ_Aux->First();
	TStringList *ListaFolios = new TStringList(this);
	int i = 0;
	while(!SQLQ_Aux->Eof)
	{
		ListaFolios->Strings[i] = SQLQ_Aux->FieldByName("NumeroFolio")->AsString;
		i++;
		SQLQ_Aux->Next();
	}
	return ListaFolios; // This line is marked with red color by compiler
}


And my .h code:
	TStringList ObtieneListaFolioAsignadoVendedor(int IdVendedor, int TipoFolio);

What I'm doing wrong or incorrect?
Any help would be appreciated.

Best regards,
Patricio Cerda

Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Error message returning a TStringList
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 29, 2018 10:09 AM   in response to: Patricio Cerda in response to: Patricio Cerda
Patricio Cerda wrote:

I'm working with C++Builder Berlin 10.1 and trying to define a method
on the server side of my DataSnap server, where I must to return a
TStringList, but the compiler show me the following error message:
"Delphi style classes must be constructed using operator new" and
also shows in red color the last line of the .cpp code).

You are trying to return a TStringList object by value. That will
not work for classes that are derived from TObject.

For Delphi compatibility reasons, TObject must be allocated on the
heap, just as the compiler error says. Which you are doing for your
ListaFolios variable (BTW, TStringList does not have a constructor that
acccepts 'this' as input), but you are not doing that for your function
return value. It is being constructed on the call stack instead, thus
the compiler error.

Even if TStringList could be constructed on the stack (which it can't),
your code would still fail to compile, because you are returning a
object pointer where an object instance is expected.

Also, You are trying to use the TStringList::Strings[] property to add
new strings to the TStringList. You can't use the Strings[] property
that way. It can only modify existing strings, not add new strings.
Since you don't know the number of strings being added, you need to use
the TStringList::Add() method instead.

Try something more like this:

TStringList* ObtieneListaFolioAsignadoVendedor(int IdVendedor, int
TipoFolio);
 
...
 
TStringList* TDSSM_VentasAlahora::ObtieneListaFolioAsignadoVendedor(int
IdVendedor, int TipoFolio)
{
    TStringList *ListaFolios = new TStringList;
    try
    {
        SQLQ_Aux->Active = false;
        SQLQ_Aux->SQL->Text = "select NumeroFolio from FoliosContratos
where IdVendedor = " + String(IdVendedor) + " and IdTipoContrato = " +
String(TipoFolio) + " and IdEstado = 2 order by Id asc";
        SQLQ_Aux->Active = true;
        try
        {
            for (SQLQ_Aux->First(); !SQLQ_Aux->Eof; SQLQ_Aux->Next())
            {
 
ListaFolios->Add(SQLQ_Aux->FieldByName("NumeroFolio")->AsString);
            }
        }
        __finally
        {
            SQLQ_Aux->Active = false;
        }
    }
    catch (const Exception &)
    {
        delete ListaFolios;
        throw;
    }
    return ListaFolios;
}


--
Remy Lebeau (TeamB)
Patricio Cerda

Posts: 122
Registered: 3/13/01
Re: Error message returning a TStringList
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 31, 2018 2:35 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
You are trying to return a TStringList object by value. That will
not work for classes that are derived from TObject.

For Delphi compatibility reasons, TObject must be allocated on the
heap, just as the compiler error says. Which you are doing for your
ListaFolios variable (BTW, TStringList does not have a constructor that
acccepts 'this' as input), but you are not doing that for your function
return value. It is being constructed on the call stack instead, thus
the compiler error.

Even if TStringList could be constructed on the stack (which it can't),
your code would still fail to compile, because you are returning a
object pointer where an object instance is expected.

Also, You are trying to use the TStringList::Strings[] property to add
new strings to the TStringList. You can't use the Strings[] property
that way. It can only modify existing strings, not add new strings.
Since you don't know the number of strings being added, you need to use
the TStringList::Add() method instead.

Try something more like this:

TStringList* ObtieneListaFolioAsignadoVendedor(int IdVendedor, int
TipoFolio);
 
...
 
TStringList* TDSSM_VentasAlahora::ObtieneListaFolioAsignadoVendedor(int
IdVendedor, int TipoFolio)
{
    TStringList *ListaFolios = new TStringList;
    try
    {
        SQLQ_Aux->Active = false;
        SQLQ_Aux->SQL->Text = "select NumeroFolio from FoliosContratos
where IdVendedor = " + String(IdVendedor) + " and IdTipoContrato = " +
String(TipoFolio) + " and IdEstado = 2 order by Id asc";
        SQLQ_Aux->Active = true;
        try
        {
            for (SQLQ_Aux->First(); !SQLQ_Aux->Eof; SQLQ_Aux->Next())
            {
 
ListaFolios->Add(SQLQ_Aux->FieldByName("NumeroFolio")->AsString);
            }
        }
        __finally
        {
            SQLQ_Aux->Active = false;
        }
    }
    catch (const Exception &)
    {
        delete ListaFolios;
        throw;
    }
    return ListaFolios;
}


--
Remy Lebeau (TeamB)

Everything here is clear and working with your explanation and suggestion, thank you Remy.
Another questions that I have on this matter and may be you could help me with is: How could I create my own C++ class on the server side and then pass it to the client side using DataSnap?

Best regards,
Patricio Cerda
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02