Posts

C++/CLI: Destructors VS Finalizers

Spanish version / Versión en Español Even though in C# destructor and finalizer are the same thing because C# is garbage collected, in C++/CLI things are quite different. This is because C++/CLI has both deterministic (destructors) and non deterministic destruction (finalizers). Destructors are deterministically invoked when an object created on the managed stack goes out of scope; on the other hand, finalizers are called by .NET's Garbage Collector when its heuristic says so. That is why it's called non-deterministic destruction. La sintaxis: //This generates C4251 public ref class A(){ //Fields public: A(); ~A(); //Destructor !A(); //Finalizer void f(); } The destructor is automatically called when an instance of A created on the managed stack (without using gcnew/new/New) goes out of scope, and also when the Dispose method is called on an instance created on the managed heap (gcnew/New). This is because the C++/CLI compiler maps the destr...

C++/CLI: Destructores VS Finalizers

Versión en inglés / English version Aunque en C# estas dos palabras representan lo mismo, dado que C# es un lenguaje con recolección de basura, en C++/CLI la cosa es muy diferente. Esto se debe a que dicho lenguaje tiene tanto destrucción determinística (destructores) como no determinística (finalizers). Los destructores son invocados determinísticamente al irse de scope el objeto; por otro lado, los finalizers son invocados por el recolector de basura de .NET cuando su heurística lo indique. Es por ello que dicha destrucción se denomina "no deterministica." La sintaxis: //Esto genera C4251 public ref class A(){ //Atributos public: A(); ~A(); //Destructor !A(); //Finalizer void f(); } El destructor es invocado cuando una instancia de A creada en el managed stack (o sea, sin usar gcnew/New/new) se va de scope, y cuando se invoca Dispose sobre una instancia creada en managed heap. Esto último es porque el compilador de C++/CLI mapea el dest...

C++/CLI: Convert a String to BSTR or some other nasty stuff

Spanish version / Versión en Español This is very usual when replacing a COM interface with a C++/CLI wrapper (Guess who's doing that?). That usually leads to the need to convert a .NET string (System::String^) to a BSTR, or a std::string. Luckily, .NET provides some handy conversion functions for this. They save us the hassle of creating buffers, releasing them and whatnot. Among them are the marshal_as functions and the marshal_context class. Here's the lowdown for when to use which: Overview of Marshalling in C++

C++/CLI: Transformar un String a BSTR u otras cochinadas

Versión en inglés / English version Esto es muy común cuando uno quiere reemplazar una interfaz COM por una C++/CLI. Esto típicamente requiere convertir System::String^ a BSTR, std::string y otras yerbas. Por suerte, .NET nos provee una solución que nos evita andar copiando cosas a buffers y viendo cuándo las liberamos: El método marshal_as y la clase marshal_context. Acá está el detalle de qué usar para cada conversión: Overview of Marshalling in C++

C++: Warning C4251: Templates in exported classes

Spanish version / Versión en Español Say you have a template, be it from the STL or custom, as a field in a class which is __declspec(dllexport)'ed, you'll get this warning. The problem is that we're trying to export the template's declaration without its definition. This can make our program crash in runtime if we combine binaries which use different versions of the STL or our template. This could happen if we used dll's compiled with different versions of Visual Studio. If you can't (or you're lazy) refactor your code in order not to export the class (you should only export interfaces), what you can do is export not the whole class but only the public methods which are used from other assemblies. Generically, if we have... //This generates C4251 class __declspec(dllexport) A(){ public: A(); virtual ~A(); void f(); private: std::vector<int> m_vGeneratesC4251; } ... and this dll's client assembly only needs to access f...

C++: Warning C4251: Templates en clases exportadas

Versión en inglés / English version Si uno tiene un template, sea de la STL o propio, como atributo en una clase exportada con __declspec(dllexport), nos salta este warning. El problema reside en que estamos exportando la declaración del template, sin su definición. Esto puede hacer que nuestro programa explote en tiempo de ejecución si combinamos binarios con diferentes versiones de la STL o de nuestro template. Esto puede ocurrir si usamos dll's compiladas con diferentes versiones del Visual Studio. Si no podemos (o nos da fiaca) hacer refactoring para no exponer atributos en una clase exportada (idealmente, sólo deberíamos exportar interfaces), lo que podemos hacer es exportar no toda la clase sino sólo los métodos que se usan afuera. De forma genérica, si tenemos... //Esto genera C4251 class __declspec(dllexport) A(){ public: A(); virtual ~A(); void f(); private: std::vector<int> m_vGeneraC4251; } ... y el cliente de esta dll sólo necesita ac...

C++: Parse input skipping whitespace

Spanish version / Versión en Español Still re-reading Stroustrup's book , I found something I'd like to have known some time ago: an elegant way to parse an input stream for words separated by whitespace (1 whitespace = any amount of consecutive space and/or tabs). This can be done using an istream_iterator, like so: #include <fstream> #include <iostream> #include <algorithm> #include <vector> void main(){ using std::cout; using std::endl; // We read from standard input, but it could just as well be a file std::istream_iterator<std::string> ii( std::cin ); cout << "--->Input whitespace-separated words:" << endl; // Suppose we stop reading when we find the word "END" std::vector<string> words; while ( *ii != "END" ){ cout << *ii << endl; words.push_back(*ii); ii++; } // Sort words cout << "Sorted words:...