Pages

Showing posts with label MS. Show all posts
Showing posts with label MS. Show all posts

Hello Windows Sockets 2 - client

The Winsock API is a collection of quite low level functions. As we have seen in the previous post, writing an echo server, substantially a simple procedure (wait for data, send them back, shutdown when the connection closes), it is not complicated but longish, we have access to the tiniest detail in the process. The most tedious part of the job is that we have to specify any single step by hand, even the ones that could be easily automatized. A slender C++ wrapper would be enough to make the job much more simpler, but till now I haven't found around anything like that. Any suggestion is welcomed.

Let's now complete our echo application, thinking about the client side.

Initializing Winsock

This is the same stuff that we have already seen for the server side. We need to enclose out code in a pair of function call to WSAStartup() and WSACleanup(), the Ws2_32.lib should be linked to our project, and we have to include a couple of header files, winsock2.h and ws2tcpip.h, in our C/C++ source file.

Open/close socket

Almost the same as for the server:
void client(const char* host, const char* port) // 1
{
    ADDRINFO hints;
    wsa::set(hints, 0, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); // 2

    ADDRINFO* ai = wsa::get(host, port, &hints);
    if(ai)
    {
        wsa::list(ai); // 3

        SOCKET sk = wsa::createClientSocket(ai);
        freeaddrinfo(ai);

        if(sk != INVALID_SOCKET)
        {
            coreClient(sk); // 4
            closesocket(sk);
        }
    }
}
1. The user should provide us both machine address an port, so that we can connect to the server socket.
2. Tiny variation, we specify AF_UNSPEC as address family, so that both TCP/IP v4 and v6 are accepted, when available. This does not make much sense here, since we already know that the server is using a TCP/IP v4, but in a real case scenario could be a useful trick.
3. We asked to winsock for all the address info matching our requirements. If its current version supports both TCP/IP v4 and v6, we should get both of them. This tiny utility function, see it below, checks all the retrieved address info and dump to the console some of their settings.
4. The rest of the code is just the same of what we have already seen for the server, before calling the specific client code, we create the socket, and then we'll close it. Notice also that we had to free by hand the memory associated to the address info.

As promised, here is the address info listing utility function:
namespace wsa
{
    void list(ADDRINFO* ai)
    {
        while(ai)
        {
            std::cout << ai->ai_family << ' ' << ai->ai_socktype << ' ' << ai->ai_protocol << std::endl;
            ai = ai->ai_next; // 1
        }
    }
}
1. ADDRINFO is actually a linked list of records. Its ai_next field points to the next element, if any. So here we are looping on all the items available.

Send and receive

Here is the client specific code:
void coreClient(SOCKET sk)
{
    char* message = "Hello Winsock 2!";

    int size = send(sk, message, strlen(message), 0); // 1
    if(size == SOCKET_ERROR)
    {
        std::cout << "send failed: " << WSAGetLastError() << std::endl;
        return;
    }

    std::cout << size << " bytes sent" << std::endl;

    if(shutdown(sk, SD_SEND) == SOCKET_ERROR) // 2
    {
        std::cout << "shutdown failed: " << WSAGetLastError() << std::endl;
        return;
    }

    do { // 3
        char buffer[BUFLEN];
        size = recv(sk, buffer, BUFLEN, 0); // 4
        if(size > 0)
        {
            std::cout << "Buffer received: '";
            std::for_each(buffer, buffer + size, [](char c){ std::cout << c; });
            std::cout << '\'' << std::endl;
        }
        else if(!size)
            std::cout << "Connection closed." << std::endl;
        else
            std::cout << "recv failed: " << WSAGetLastError() << std::endl;
    } while(size > 0);
}
1. The message is sent through the socket, winsock returns the number of bytes actually sent, or an error code.
2. This simple application sends just one message, so here we can already close the send component of the socket, releasing some resources doing that, still keeping alive its receive component.
3. Loop until we receive data from the server
4. The received data is put in the buffer, its size is returned by the call. A zero size message is interpreted as a shutdown signal coming from the server. A negative value has to be intepreted as an error code.

If we run the client alone, it won't find any server socket to connect, and would return an error to the user.

The full client/server source code is on github.

Go to the full post

Hello Windows Sockets 2 - server

The Winsock API, also known as WSA, implements the socket paradigm not much differently from the BSD (Berkeley Software Distribution) concept. Here I am going to write a simple echo application that should help to familiarize with its basic functionality.

Initializing Winsock

To use Winsock 2 we need to link Ws2_32.lib (if the 32 bit version is OK for you), and we can do that specifying it in the project Properties - Linker - Input - Additional Dependencies field. Alternatively, we could use a pragma directive:
#pragma comment(lib, "Ws2_32.lib")
Then include files required are winsock2.h and, almost ever, ws2tcpip.h, the WinSock2 extension for TCP/IP protocols header.

The winsock code should be within two calls that take care of initializing and shutting down the socket support. Typically your code should look like:
WSADATA wsaData; // 1
int failCode = WSAStartup(MAKEWORD(2,2), &wsaData); // 2
if(failCode)
{
    std::cout << "WSAStartup failed: " << failCode << std::endl;
    return;
}

// 3
// ...

WSACleanup(); // 4
1. WSADATA is a structure containing a few data related to the current active Winsock API.
2. WSAStartup() try to initialize winsock for the passed version support (2.2 here) and sets the wsadata structure. If it works fine it returns 0, otherwise it returns an error code.
3. Your winsock code goes here.
4. Winsock shutdown.

Open/close socket

To create a socket we need to specify an ADDRINFO structure. Here is the how to for the server:
void server(const char* port) // 1
{
    ADDRINFO hints;
    wsa::set(hints, AI_PASSIVE, AF_INET, SOCK_STREAM, IPPROTO_TCP); // 2

    ADDRINFO* ai = wsa::get(NULL, port, &hints); // 3
    if(ai)
    {
        SOCKET sk = wsa::createServerSocket(ai); // 4
        freeaddrinfo(ai); // 5

        if(sk != INVALID_SOCKET)
        {
            coreServer(sk); // 6
            closesocket(sk);
        }
    }
}
1. The user tells on which port the socket should sit.
2. See below for this tiny utility function I have written thinking it makes the code clearer. The addrinfo is initialize to say to winsock that we want to create a server TCP v4 socket.
3. A second tiny utility function of mine, to wrap a call to getaddrinfo() that returns an available addrinfo matching our request, or NULL.
4. Another utility function, this one wrapping a call to socket(), that creates a winsock socket, and bind() it to the passed address.
5. Once we get the socket, we can get rid of the addrinfo.
6. If we have got a good socket, we can do the real job.
7. We are done with the socket, so we close it.

Let see the utility functions used above:
namespace wsa
{
    void set(ADDRINFO& that, int flags =0, int family =0, int type =0, int protocol =0, // 1
        size_t addrlen =0, char* name =0, SOCKADDR* addr =0, ADDRINFO* next =0)
    {
        that.ai_flags = flags;
        that.ai_family = family;
        that.ai_socktype = type;
        that.ai_protocol = protocol;
        that.ai_addrlen = addrlen;
        that.ai_canonname = name;
        that.ai_addr = addr;
        that.ai_next = next;
    }

    ADDRINFO* get(const char* host, const char* port, ADDRINFO* hints)
    {
        ADDRINFO* ai = NULL;
        int failCode = getaddrinfo(host, port, hints, &ai); // 2
        if(failCode)
        {
            std::cout << "getaddrinfo failed: " << failCode << std::endl;
            return NULL;
        }
        return ai;
    }

    SOCKET createSocket(ADDRINFO* ai) // 3
    {
        SOCKET sk = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
        if(sk == INVALID_SOCKET)
        {
            std::cout << "error creating socket: " << WSAGetLastError() << std::endl;
            return INVALID_SOCKET;
        }
        return sk;
    }

    SOCKET createServerSocket(ADDRINFO* ai)
    {
        SOCKET sk = createSocket(ai); // 4

        if(sk != INVALID_SOCKET && bind(sk, ai->ai_addr, ai->ai_addrlen) == SOCKET_ERROR) // 5
        {
            closesocket(sk); // 6

            std::cout << "Unable to bind: " << WSAGetLastError() << std::endl;
            return INVALID_SOCKET;
        }
        return sk;
    }
}
1. It ensures all the fields are set to zero/NULL or to a valid value.
2. Wraps a call to getaddrinfo().
3. First step in the creation of a server socket, it wraps a call to socket().
4. After creating a socket in (3) ...
5. ... we bind it to the passed address.
6. Some error handling.

Accepting a client

After all this setting up, we can finally do something with our socket:
void coreServer(SOCKET skServer)
{
    if(listen(skServer, SOMAXCONN) == SOCKET_ERROR) // 1
    {
        std::cout << "Listen failed with error: " << WSAGetLastError() << std::endl;
        return;
    }

    SOCKET skClient = accept(skServer, NULL, NULL); // 2
    if(skClient == INVALID_SOCKET)
    {
        std::cout << "accept failed: " << WSAGetLastError() << std::endl;
        return;
    }

    echoLoop(skClient); // 3
    closesocket(skClient);
}
1. We have a passive (server) socket, bound to a specific address. Before working on it, we have to prepare it to listen for incoming traffic.
2. Here we hangs till we receive an input from a client socket. In this simple example, there could be just one client accessing the server. Once the server accepts a client connection, it has no way to accept another one of them.
3. The real job is done here.
4. And finally we close the client socket.

Receive and send

We have the client socket counterpart. We can receive on it, and send back some data to it. Here we implements an echo procedure:
void echoLoop(SOCKET skClient)
{
    char buffer[BUFLEN];

    int rSize;
    do {
        rSize = recv(skClient, buffer, BUFLEN, 0); // 1
        if(rSize > 0)
        {
            std::cout << "Buffer received: '";
            std::for_each(buffer, buffer + rSize, [](char c){ std::cout << c; });
            std::cout << '\'' << std::endl;

            int sSize = send(skClient, buffer, rSize, 0); // 2
            if(sSize == SOCKET_ERROR)
            {
                std::cout << "send failed: " << WSAGetLastError() << std::endl;
                return;
            }
            std::cout << sSize << " bytes sent back" << std::endl;
        }
        else if(rSize == 0)
            std::cout << "closing connection ..." << std::endl;
        else
        {
            std::cout << "Error receiving: " << WSAGetLastError() << std::endl;
            return;
        }
    } while(rSize > 0);
}
1. Receive until the client shuts down the connection
2. Echo the buffer back to the sender

If we run the server alone, it will hang forever waiting for a client. We'll see it in the next post, but you can already go to github and get the full client/server source code. This example is based on the official Getting started with Winsock topic on MSDN.

Go to the full post

Hello C#

Given my background, C# looks strangely familiar. Sort of a jump in a parallel dimension. It is close to Java, but it is actually not the same. It remembers C++, being definitely something else. And it even has something of old dear Pascal in its Delphi flavour.

Here is how to say hello, writing to the console:

class Hello
{
public static void Main()
{
System.Console.WriteLine("Hello C#");
System.Console.ReadLine();
}
}

Notice the (wierd, from my point of view) uppercase initial for function names.

Using the GUI interface is almost as simple as writing to the console:

using System.Windows.Forms; // 1.

class Hello
{
public static void Main()
{
System.Windows.Forms.MessageBox.Show("Hello C#");
}
}

The only (and minor) issue is that we have to tell the compiler where to get the System.Windows.Forms namespace. System.Console is so standard that we have not to bother about, but this other one has to be specified.

We have to insert in the project an "assembly reference" to the required additional packages. Luckly this is done in a very intuitive mode in the developing environment.

Go to the full post

asp:Calendar

Besides the standard HTML elements, ASP let us use a bunch of custom controls, like asp:Calendar.

As example, we are going to create an asp:Calendar control that let us select a day, a week, or an entire month.

Here is the snippet from the changed code in the HTML-body-form section:

<asp:Calendar id="myCalendar" runat="server"
OnSelectionChanged="newDateSelection"
SelectionMode="DayWeekMonth" />
<asp:Label id="myDay" runat="server" />
<p><button id="myReset" onserverclick="resetData"
runat="server">Reset</button></p>

We have created an asp:Calendar with the aforementioned selection mode and the specification to call a method called newDateSelection() when the event selectionChange occurs.
We also have an asp:Label myDay that is going to show to the user the current selection.
And finally we have an HTML button, myReset, that we plan to use to clear the selection in the calendar. To get this task done, it calls the method resetData(), that we are about to write.

Here is the associated C# code:

protected void Page_Load(Object s, EventArgs e) // 1.
{
myCalendar.SelectedDate = myCalendar.TodaysDate;
newDateSelection(s, e);
}

void resetData(Object s, EventArgs e) // 2.
{
System.Diagnostics.Debug.WriteLine("resetData()");
myCalendar.SelectedDate = new DateTime();
newDateSelection(s, e);
}

void newDateSelection(Object s, EventArgs e) // 3.
{
myDay.Text = "";

switch(myCalendar.SelectedDates.Count)
{
case 0:
myDay.Text = "No date selected";
break;
case 1:
myDay.Text = myCalendar.SelectedDate.ToShortDateString();
break;
default:
myDay.Text = "From " + myCalendar.SelectedDates[0].ToShortDateString();
myDay.Text += " to " +
myCalendar.SelectedDates[myCalendar.SelectedDates.Count-1].ToShortDateString();
break;
}

myDay.Text += "<br />";
}

1. We want to do some setting up on the calendar control. A good place to do that is when the page is loaded, so we change the Page_Load() method. The setup is actually about selecting the current day in the calendar. Here we change the SelectedDate property for our calendar, setting it to the TodayDate (again a property for the calendar object itself), then we delegate to another method of ours, newDateSelection(), the job of displaying to the user what we have done.
2. This is the method called when we push the reset button. Its first line is there almost just to show how to add some debug message to our code. The second line does the dirty job of creating a new DataTime object with no parameter - the result is what is (usually) considered a fake date, that in this context means no data selected. And finally we call newDateSelection().
3. This method takes care of displaying to the user the date(s) currently selected in the calendar, putting the result in the asp:Label myDay. If we have selected an interval of dates, we show just the first and the last day.

Go to the full post

Using HTML elements

It is quite easy to let ASP use an HTML control. Basically, we put it in the pre-generated form in the ASP page, we give it a runat attribute set to "server", and that it. OK, when used in ASP context the HTML controls require a slight different setting.

For instance the multiple attribute of the select element has to be set to true to show that it is a multiple select, and not to "multiple" as the standard specify. It would be ASP itself to convert it to the HTML code expected on client side.

Here is an example where we create a sort of feedback page for a blog that is about computer programming. We create an HTML input text, myName, where the reader could enter his name; then a multiple select, myLanguages, for the programming languages used; another input text, myOther, for entering more programming languages; another select (but this one is not a multiple one), myInterest, to let the reader give a feedback; a button, myButton, to ask ASP to run the associated C# code; and finally a label, myLabel, where putting the result.

Here is the resulting ASP page:

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
void click(Object s, EventArgs e)
{
myLabel.Text = "Feedback from "
+ (myName.Value.Count() != 0 ? myName.Value : "anonymous") + "<br />"
+ "preferred languages: ";

bool anyLanguage = false;
for (int i = 0; i < myLanguages.Items.Count; ++i)
{
if (myLanguages.Items[i].Selected)
{
anyLanguage = true;
myLabel.Text += myLanguages.Items[i].Text + " ";
}
}
if (anyLanguage == false)
myLabel.Text += "not specified";
myLabel.Text += "<br />";

if(myOther.Value.Count() != 0)
myLabel.Text += "Other: " + myOther.Value + "<br />";

myLabel.Text += "Has been the blog useful? " + myInterest.Value;
}
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Feedback</title>
</head>
<body>
<form id="myForm" runat="server">
<div>
<h2>Feedback</h2>
<p>Name:<br /><input type="text" id="myName" runat="server" /></p>
<p>Which programming languages do you currently use?<br />
<select id="myLanguages" runat="server" multiple="true">
<option>C</option>
<option>C++</option>
<option>C#</option>
<option>Java</option>
<option>Perl</option>
<option>SQL</option>
<option>Other</option>
</select>
</p>
<p>If other, please specify:<br />
<input type="text" id="myOther" runat="server" /></p>
<p>Have you found anything interesting in here?<br />
<select id="myInterest" runat="server">
<option>Yes</option>
<option>No</option>
</select>
</p>
<p><button id="myButton" onserverclick="click" runat="server">Confirm</button></p>
<p><asp:Label id="myLabel" runat="server" /></p>
</div>
</form>
</body>
</html>

Relatively speaking, we have written quite a lot of C# code in this example.

Go to the full post

Push my button

Let's see how to use a button in an ASP page.

We'll have a text box (aka input line) where entering a string; and a button to push when done with it. A function would be then called, that would read the string we input and write it in a label.

Being such a simple code, we will put all directly in the ASP page.

I'm using an asp:TextBox named myTextBox; an asp:Button, myButton, with the associated text "OK" and the OnClick even handler associated to a method named click; and finally an asp:Label named myLabel.

The click() method would simply say that the text in myTextBox should be assigned to the text of myMessage.

Here is the resulting ASP page:

<%@ Page Language="C#"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
void click(Object s, EventArgs e)
{
myMessage.Text = myTextBox.Text;
}
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Push me</title>
</head>
<body>
<form id="myForm" runat="server">
<div>
<asp:TextBox id="myTextBox" runat="server" />
<asp:Button id="myButton" text="OK" runat="server" onClick="click" />
<hr />
Your input message is: <asp:Label id="myMessage" runat="server" />
</div>
</form>
</body>
</html>

Go to the full post

Simpler Hello ASP

Actually, for such a simple ASP page like the one we developed in the previous post, using a separate C# file is a bit of an overkill.

We could have instead add to the ASP page just the C# script fragment we need. If we ask to the wizard not to add a separate file for the C# code, we get a slimmer page, that we could easily modify to add our code in a specific script tag.

Here is an ASP page doing exactely the same job of the previous example:

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
myTime.Text = DateTime.Now.ToString();
}
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Hello Even Simpler</title>
</head>
<body>
<form id="form1" runat="server">
<div>
Hello from Even Simpler. Current time is <asp:Label id="myTime" runat="server"/>
</div>
</form>
</body>
</html>

Go to the full post

Hello ASP

Here is a simple ASP page developed with Visual Web Deveoper.using C# as programming language.

I won't spend time on the (long and boring) time required to install on my machine the developing environment, because I don't not know what to say more than it was a long and boring process.

In any case. I have created a new project for an empty Web ASP-NET application. Then in the application I created a new Web Form, and I kept the proposed name (even if I don't expecially like it), Default.aspx. In the process, another file happened to be created, Default.aspx.cs, that looks quite clearly it is a C# file strongly connected with the ASP page.

Here is the source file for the ASP page, slightly change to provide a HTML page title, and some text in the body:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Hello Simple</title>
</head>
<body>
<form id="form1" runat="server">
<div>
Hello from Simple. Current time is <asp:Label id="myTime" runat="server"/>
</div>
</form>
</body>
</html>

In the first line you see a Page directive where it is specified, among other stuff, that we are using C# as undelying language and the name of the file where to look for the C# code.

In the body we can see that a put an asp:Label, that is nothing more than a label, but it has a funny property runat set to server, obviously meaning that is something that has to run on the server. We keep note also of the other property, ID, that looks like a way of providing access to this element.

Actually, if we have a look to the C-Sharp code, we understand more of the asp:Label, since I put there a line referring to it:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(Object sender, EventArgs e)
{
myTime.Text = DateTime.Now.ToString();
}
}

All this code was automatically generated but the body of the Page_Load() method. Even not knowing a thing of C# and ASP.NET, it looks that here we are dealing with a class containing code related with a web page, that is picked up as default and that its proposed method is called when the page is loaded, passing an "Object" representing the sender and an "EventArgs" that should be the associated event that caused the method to be called.

What we are doing here is simply setting the Text property of the myTime label, defined in the ASP page, using the current system time converted to a string.

When I executed the project I saw an HTML page having this code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>
Hello Simple
</title></head>
<body>
<form method="post" action="Default.aspx" id="form1">
<div class="aspNetHidden">
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJ(...)Grg==" />
</div>

<div>
Hello from Simple. Current time is <span id="myTime">13/02/11 22:59:16</span>

</div>
</form>
</body>
</html>

Bad formatting, some funny stuff, but, besides this, the most interesting line is in the body, where our asp:Label has been converted in good HTML code.

Go to the full post

System::IO

To access a file it is possible to use the System::IO::FileStream that provides access to the low level details of a file.

As example, we write a function, readFile(), that access a file and put its content in a managed array:

void readFile(System::String^ filename)
{
using System::IO::FileStream;
using System::IO::FileMode;

FileStream^ fs = gcnew FileStream(filename, FileMode::Open); // 1.

long long len = fs->Length;

System::Console::WriteLine("File length is {0}", len);

int size = static_cast(len); // 2.
array^ content = gcnew array(size);
fs->Read(content, 0, size);
fs->Close();
}

1. since we specify the mode FileMode::Open, if the file does not exists, an exception is thrown.
2. the length of a FileStream is defined as a long long, but the size of an array in just an int. Instead of simply casting to int, as we did here, we should add a bit of logic, to properly read all the file.

If we expect the file to be a text one, we could use StreamReader and TextWriter:

void readTextFile(System::String^ filename)
{
using System::IO::StreamReader;
using System::IO::TextWriter;

StreamReader^ sr = gcnew StreamReader(filename);
TextWriter^ tw = System::Console::Out;
tw->WriteLine("File {0}:", filename);

System::String^ line;
for(int i = 0; (line = sr->ReadLine()) != nullptr; ++i)
tw->WriteLine("Line {0}: {1}", i, line);

sr->Close();
}

This post is based on my reading on the book "Expert C++/CLI: .NET for Visual C++ Programmers" by Marcus Heege, APress.

Go to the full post

Command line arguments

It is commonly known that to output the command line arguments for a standard C++ program we could write a piece of code like that:

int main(int argc, char** argv)
{
for (int i = 0; i < argc; ++i)
std::cout << "Argument " << i << ": " << argv[i] << std::endl;

system("pause");
}

Where the first argument is the name of the program itself.

To achieve something similar in C++/CLI we write this:

int main(cli::array^ args)
{
for (int i = 0; i < args->Length; ++i)
System::Console::WriteLine("Argument {0}: {1}", i, args[i]);

system("pause");
}

I wrote "similar" not for the fact that we deal with System::Strings instead of raw arrays of chars - this is just an implementation details, after all - but because the program name is not in the argument lists.

To be a bit more pedantic, the managed version of the main function for a C++/CLI program accepts in input a managed array of managed System::String. The environment puts in this array any argument passed to the program.
This post is based on my reading on the book "Expert C++/CLI: .NET for Visual C++ Programmers" by Marcus Heege, APress.

Go to the full post

Using .NET classes

To use .NET classes that are defined in a specific dll we have to use a Microsoft extension to the preprocessor: the directive using.

The exception is the core library, mscorlib.dll, that requires no using directive to be available to our code. In this way we can use Console, Object, and many other basic stuff without explicit preprocessor using.

In this short example we use the class System::Uri that is defined in the System.dll:

#using

void exp03()
{
System::Uri^ uri = gcnew System::Uri("http://www.heege.net");
System::Console::WriteLine(uri->Host);
}

This post is based on my reading on the book "Expert C++/CLI: .NET for Visual C++ Programmers" by Marcus Heege, APress.

Go to the full post

Managed array

To create a manged array we should just specify the type and the number of dimensions. The default is a dimension of one. The array keyword, not a standard C++ keyword, is defined in the pseudo namespace cli, that could be used to avoid conflicts.

A managed array is initialized like a standard C++ array:

cli::array^ square = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};

cli::array^ square2 = gcnew array(3, 3);
for(int i = 0; i < 3; ++i)
for(int j = 0; j < 3; ++j)
square2[i, j] = (i * 3) + (j + 1) ;

The dimension of the array is not part of the array type specification, and, as for the other .NET object, once created an array can't change its size. The System::Array::Resize function does not actually resize the passed array, but just create a new one with the new dimensions and then copy the data from the original one.

The initialization of a managed array differs from the one of a standard C++ one in the way that all the element are always initialized to zero and then its default constructor is called, if available.

This post is based on my reading on the book "Expert C++/CLI: .NET for Visual C++ Programmers" by Marcus Heege, APress.

Go to the full post

CTS System::String and System::Text::StringBuilder

Any System::String object is immutable. That means, for instance, that calling String::Concat() does not change the passed object, but return a newly allocated System::String.

Here is a short example that should clarify how System::String works:

System::String^ str1 = System::String::Empty; // 1.
str1 += "a";
str1 = str1 + "a";
str1 = System::String::Concat(str1, "a");
System::Console::WriteLine(str1); // 2.
System::String^ str2 = str1->ToUpper();
System::Console::WriteLine(str2); // 3.

1. overkilling, Concat() is smart enough to manage nullptr System::String in input
2. the three lines before have the same effect, so now we have "aaa" in str1
3. notice that ToUpper() does not change str1, it just creates a new System::String

To avoid the creation of many unncecessary temporary strings is often useful using System::Text::StringBuilder, a sort of mutable string. It coulb be used in this way:

using System::Text::StringBuilder;
StringBuilder^ sb = gcnew StringBuilder(1024);
sb->Append("Rows: \n");
for (int i = 0; i < 100; ++i)
sb->AppendFormat("Row {0}\n", i);
System::String^ str3 = sb->ToString();
System::Console::WriteLine(str3);


This post is based on my reading on the book "Expert C++/CLI: .NET for Visual C++ Programmers" by Marcus Heege, APress.

Go to the full post

Managed Heap

The heap memory management in .NET is based on the concept of garbage collection, this has many advantages but a huge problem: it doesn't match with the standard C++ model.

So, C++/CLI introduces a specific operator, gcnew, to allocate memory on the managed heap. This operator returns something like a pointer to the managed memory, that is called tracking handle to stress the fact that it is not a native C++ pointer, and is denotated by ^ (caret) instead of * (asterisk). Instead of NULL, the invalid value for a tracking handle is nullptr. To access members through a tracking handle is used the same arrow operator used to access members through a standard C++ pointer. Curiously enough, to dereference a tracking handle a * (asterisk) is used.

Here is piece of code that should clarify the matter:

int^ i; // 1.

if(i == nullptr)
std::cout << "i is initialized to nullptr" << std::endl;

i = gcnew int(42); // 2.
if(i != nullptr)
{
System::Console::WriteLine(i->GetType()); // 3.
System::Console::WriteLine(i->ToString()); // 4.

std::cout << "i has value " << *i << std::endl; // 5.
}

1. define a tracking handle, implicitly initialized to nullptr.
2. an int object is created on the managed heap, its tracking handle is returned, and stored in the local variable
3. the tracking handle is dereferenced to call the GetType() method. System.Int32 should be printed, since int is converted to that type on the managed memory.
4. this instruction would print the value of the int object on the managed heap, that means 42.
5. here we print the derefenced value of i, again 42.

This post is based on my reading on the book "Expert C++/CLI: .NET for Visual C++ Programmers" by Marcus Heege, APress.

Go to the full post

CTS and primitive types

There is a hierarchy of classes that should be used to help language interoperability in .NET, it is called CTS (Common Type System) and it is based on the System::Object class. So, anything in CTS is a System::Object.

That means that we can call on any CTS object the System::Object method:
  • ToString;
  • GetType, provides RunTime Type Information (RTTI) in .NET;
  • GetHashCode;
  • Equals.

C++/CLI it is smart enough to use primitive types as managed types, so having a way to work on them as System::Objects.

So this code would output to console System.Int32:

System::Console::WriteLine((42).GetType()); // System.Int32

Here is the mapping the primitive C++ type and the CTS classes that wrap each of them, and some examples of its literal values:

bool System::Boolean (true)
unsigned char System::Byte
signed char System::SByte ('a')
short System::Int16
unsigned short System::UInt16
int System::Int32
unsigned int System::UInt32 (1U)
long long System::Int64 (1LL)
unsigned long long System::UInt64 (1ULL)
float System::Single (1.0f)
double System::Double (1.0)
wchar_t System::Char (L'a')
void System::Void

Even cooler, C++/CLI could use a CTS object as a primitive, when required so, this piece of code works properly:

System::Double PI = 3.14159265358979;
std::cout << PI << std:: endl;

PI is passed to cout as if it were declared as double.

This post is based on my reading on the book "Expert C++/CLI: .NET for Visual C++ Programmers" by Marcus Heege, APress. I suggest you to read it too, to have more details on the matter

Go to the full post

Hello CLI

The code we are talking about here is not proper C++, it is C++/CLI, where CLI stands for Common Language Infrastructure, and that means .NET, so we are basically talking about the C++ twisted by Microsoft to fit in its propertary architecture.

The cool thing about C++/CLI is that it is a superset of the standard C++, so we could, in principle, just avoid CLI and developing (more or less) pure C++ for our Windows platform.

Here is the usual hello program written in a way to show how C++/CLI could use C, C++ and CLI features:

#include <stdio.h>
#include <iostream>

int main()
{
printf("hello"); // C
std::cout << ", "; // C++
System::Console::WriteLine("world"); // CLI

system("pause");
}

Isn't that too bad, is it?

This post is based on my reading on the book "Expert C++/CLI: .NET for Visual C++ Programmers" by Marcus Heege, APress. I suggest you to read it too, to have more details on the matter

Go to the full post