Click to See Complete Forum and Search --> : [RESOLVED] C++/CLI stack sematics - receiving a ^


Zaccheus
January 22nd, 2007, 04:20 PM
Is there any way to receive a handle created by another member function and still use the C++/CLI stack semantics (i.e. automatic calling of Dispose) ?



I have a simple member function:


delegate void DataRecipient
(
SqlDataReader^ inSqlDataReader
);

//...

void Database::ExecuteQuery
(
String^ inSqlQuery,
DataRecipient^ inDataRecipient
)
{
// Create connection:
SqlConnection connection(ConnectionString);
SqlCommand command(inSqlQuery, %connection);

connection.Open();

// Execute query:
SqlDataReader^ reader;
try
{
reader = command.ExecuteReader();

// Give the query results to the data recipient.
inDataRecipient(reader);
}
finally
{
delete reader;
}
}


This compiles & works fine.



However, I would like use the stack semantics syntax with the SqlDataReader :


delegate void DataRecipient
(
SqlDataReader^ inSqlDataReader
);

//...

void Database::ExecuteQuery
(
String^ inSqlQuery,
DataRecipient^ inDataRecipient
)
{
// Create connection:
SqlConnection connection(ConnectionString);
SqlCommand command(inSqlQuery, %connection);

connection.Open();

// Execute query:
SqlDataReader reader( command.ExecuteReader() );

// Give the query results to the data recipient (a delegate).
inDataRecipient(%reader);
}


At the line where 'reader' is created, the compiler complains:

error C3673: 'System::Data::SqlClient::SqlDataReader' : class does not have a copy-constructor


Is it not possible to use that syntax in this way?

-------------------------------------------------------------

EDIT:

Yes! http://www.codeguru.com/forum/showthread.php?t=412448#post1582471

cilu
January 23rd, 2007, 09:33 AM
You need copy-constructor (which is not by default provided by the compiler for reference types) to employ stack semantics.

http://msdn2.microsoft.com/en-US/library/ms177191(VS.80).aspx

Since SqlDataReader doesn't seem to have one, you can't use stack semantics with it.

Zaccheus
January 23rd, 2007, 10:38 AM
I was hoping there would be a way around that.
:(

C++/CLI stack semantics are nothing more than an abstraction of the try/finally code I'm using at the moment.
The need for a 'copy constructor' seems completely illogical to me.

Anyway, thanks for your reply.

townba
February 4th, 2007, 08:08 AM
I think msclr::auto_gcroot can get you pretty close. You'd have to change a couple of lines:


#include <msclr\auto_gcroot.h>
...
msclr::auto_gcroot<SqlDataReader ^> reader(command.ExecuteReader());

// Give the query results to the data recipient (a delegate).
inDataRecipient(reader.get());

Would that be sufficient?

Zaccheus
February 13th, 2007, 09:05 AM
Thanks, that looks great.
:cool:

One concern:

MSDN says that auto_gcroot is for mixing native and managed code in the same assembly. I compile all my C++/CLI with /clr:safe which means no native code is allowed. I'll try it out and see what happens.

:)

Zaccheus
February 13th, 2007, 09:19 AM
I've just checked <msclr\auto_gcroot.h>, auto_gcroot is a native class, which means I cannot use it in my pure managed .net code.
:(

Thanks anyway.
:)

Zaccheus
June 1st, 2007, 05:05 PM
:D :D :D

I've managed to come up with a 'pure .net' solution:
Disposing a received .net pointer in C++/CLI. (http://www.rclsoftware.org.uk/cpp/cli/CppAutoDispose.html)

:wave:

bcool
January 30th, 2009, 04:22 PM
For anyone who's looking at this thread, I think auto_handle ('http://msdn.microsoft.com/en-us/library/ms177065(VS.80).aspx') should do the trick that the original poster was looking for.