JAL Computing
|
STL in a Managed EnvironmentThe STL/CLI
is now available in the Visual Studio 2008 Express Edition. // TestSTLVector.cpp : main project file. #include "stdafx.h" #include <vector> #include <string> #include <cliext/vector> #include <cliext/algorithm> #include <cliext/adapter> #include <iostream> using namespace System; using namespace cliext; // STL/CLR using namespace System::Runtime::InteropServices; using namespace System::Diagnostics; ref class Molecue { private: String^ name; public: Molecue(): name(nullptr){} // default constructor Molecue(String^ name){this->name= name;} // constructor with a parameter Molecue(const Molecue% orig) : name(orig.name) { Console::WriteLine("Copy Constructor called."); } // STL required copy constructor Molecue% operator=(const Molecue% orig) // STL required assignment operator { if (this != %orig){ // % -> tracking reference name= orig.name; Console::WriteLine("Assignment operator called."); } return *this; // support assignment chaining } ~Molecue() { Console::WriteLine("Destructor called."); } // STL required destructor property String^ Name{ String^ get() {return name;} } }; int main(array<System::String ^> ^args) { Console::WriteLine(L"Test STL/CLI Vector"); // L wide char // create objects with handles to objectss Molecue^ molecue1= gcnew Molecue(L"Hydrogen"); Molecue^ molecue2= gcnew Molecue(L"Oxygen"); // demonstrate use of handle, no call to the copy constructor Molecue^ alias2= molecue2; // demonstrate use of stack based semanitics, does call copy and assignment operator Molecue stack("Sodium"); Molecue stack1= stack; // calls copy constructor Molecue stack2; stack2= stack; // calls assignment operator // create/populate/iterate vector of handles to molecues vector<Molecue^>^ v= gcnew vector<Molecue^>; v->push_back(molecue1); v->push_back(molecue2); vector<Molecue^>::iterator it = v->begin(); for (; it != v->end(); it++) { Console::WriteLine(it->Name); } // convert array of handles to Molecues to Vector of handles to Molecues array<Molecue^>^ array1= gcnew array<Molecue^>(2); array1[0]= molecue1; array1[1]= molecue2; vector<Molecue^>^ v2= gcnew vector<Molecue^>(array1); vector<Molecue^>::iterator it2 = v2->begin(); for (; it2 != v2->end(); it2++) { Console::WriteLine(it2->Name); } // copy vector into a collection System::Collections::Generic::ICollection<Molecue^>^ iColl = make_collection<cliext::vector<Molecue^>::iterator>( v->begin() +0, // start offset 0 v->end() -0); // finish offset 0 for each (Molecue^ m in iColl) { Console::WriteLine(m->Name); } Console::ReadLine(); return 0; } Now we do some interop converting a std STL Vector of std strings to a CLI Vector of managed Strings^. // TestInterop.cpp : main project file. #include "stdafx.h" #include <vector> // std vector #include <string> // std string #include <cliext/vector> #include <cliext/algorithm> #include <cliext/adapter> using namespace System; using namespace cliext; // STL/CLR using namespace System::Runtime::InteropServices; // Marshal class Util { public: ///////////////////////////////////////////////////////// // ** ConvertSS2MS ** // // Converts std::string to managed String^ // // Parameters constant std::string in by ref // // Returns String^ out // // Static Public Class method // // Internally converts to most common denominator // // char* on heap using new and delete // // std::string ref in cannot be null, but may be empty // // Returns empty string on exception // // JAL 12/04/08 // ///////////////////////////////////////////////////////// static String^ ConvertSS2MS(const std::string& in) { String^ out= L""; // L wchar_t typedef unsigned short char* str=0; size_t size= strlen(in.c_str()) +1; // +1 for null terminator try { //const char *p= in.c_str(); // use p immediately //out= Marshal::PtrToStringAnsi(static_cast<IntPtr>(p)); // error on const char * str= new char[size]; // null terminated strcpy_s(str,size,in.c_str()); // create longer lived copy in non const char array // strcpy_s has new security enhancements over strcpy, size includes null char out= Marshal::PtrToStringAnsi(static_cast<IntPtr>(str)); // or safe_cast? } catch(...) { // eat the exception out= L""; // returns empty string on exception } finally { // clean up memory if(str) { delete [] str; // release char[] on unmanaged heap, delete [] calls destructors } } return out; } // end ConvertSS2MS }; // end class Util int main(array<System::String ^> ^args) { Console::WriteLine(L"Test STL/CLI Vector Interop"); // test standard STL to STL/CLI // fill std vector with std strings std::vector<std::string> stdVector; // value semantics stdVector.reserve(2); stdVector.push_back("Hello"); stdVector.push_back("World"); // create CLI vector of type managed Strings^ vector<String^>^ cliVector= gcnew vector<String^>; // ref semantics // possible thread safety issue here { size_t size= stdVector.size(); cliVector->reserve(size); // fill CLI vector with managed Strings^ std::vector<std::string>::iterator itStd= stdVector.begin(); for(;itStd != stdVector.end();itStd++) { cliVector->push_back(Util::ConvertSS2MS(*itStd)); } } // display contents of CLI vector vector<String^>::iterator itCli= cliVector->begin(); for(;itCli != cliVector->end();itCli++) { Console::WriteLine(*itCli); } // test for runtime errors //String^ out= Util::ConvertSS2MS(std::string("")); // succeeds with empty string //Util::ConvertSS2MS(0); // fails with null ptr Console::ReadLine(); return 0; } Have fun! |
Send mail to [email protected]
with questions or comments about this web site. Copyright © 2001, 2002, 2003,
2004, 2005, 2006, 2007, 2008, 2009 ©
|