Feeds:
Posts
Comments

Archive for the ‘C++’ Category

In really simple terms, std::move returns an argument as an rvalue reference while std::forward returns either an lvalue reference or an rvalue reference based on how the argument was passed in to the current function. While this is fairly obvious once you get the hang of it, it can be quite tricky to grasp earlier on. The easiest way to see how they work differently is to try some code such as the following:

void Show(int&&)
{
	cout << "int&& called" << endl;
}

void Show(int&)
{
	cout << "int& called" << endl;
}

template<typename T> void Foo(T&& x)
{
	cout << "straight: ";
	Show(x);

	cout << "move: ";
	Show(move(x));
	
	cout << "forward: ";
	Show(forward<T>(x));
	
	cout << endl;
}

int _tmain(void)
{
	Foo(10);

	int x=10;
	Foo(x);
	return 0;
}

The output of the above code is:

straight: int& called
move: int&& called
forward: int&& called

straight: int& called
move: int&& called
forward: int& called

When Foo is called with an rvalue, T&& is deduced as int&&. But the variable itself is an lvalue within that function. So the straight call calls the Show(int&) overload – no surprises there. Both the move-call and the forward-call calls Show(int&&) as expected. In the 2nd case, Foo is called with an lvalue, and again the straight call will go to Show(int&) while the move-call will go to Show(int&&). Now here’s where forward comes in handy, it will go to Show(int&) because that’s what T has been deduced to in this instance of the function call (perfect forwarding). If you are wondering why, the collapsing rule for T&& collapses it to T& during template argument type deduction.

Read Full Post »

If you are a C++ developer/enthusiast who lives in or around Columbus, OH, then you may be pleased to hear that we are launching a C++ specific user group in Columbus, Ohio. The first UG session is scheduled for the 14th of March. Quick Solutions, Columbus, OH has kindly agreed to host the meeting. Details below:

  • Meeting: Central Ohio C++ User Group March Meeting
  • Location: Quick Solutions Training Center at 440 Polaris Pkwy, Suite 500, Westerville, OH.
  • Date/Time: March 14th Wednesday, 6PM – 8PM
  • Session: Using Visual C++ to write WinRT/Metro applications (Speaker: Nish Sivakumar)
  • Session: Future direction of the C++ user group (Group discussion)

For a speaker bio, check out my About page here: http://www.voidnish.com/Home/About

Here’s the marketing summary:

“Nish Sivakumar is a C++ developer from Columbus, OH. He has been a Microsoft VC++ MVP since 2002 and is the author of C++/CLI in Action by Manning Publications (2006) and Extending MFC Applications with the .NET framework by Addison-Wesley (2003). He has published over 100 articles on C++, C#, WPF, WP7, WinRT, and other Microsoft technologies on The Code Project. Nish has a keen interest in photography as well as in mixology.”

Please note that we will be meeting once a month. If you live in or around Columbus, and would be interested in presenting on a C++ related topic, please get in touch with me through this blog.

March 14th Wednesday, 6PM – 8PM
440 Polaris Pkwy, Suite 500, Westerville, OH

Mark your calendars!

Read Full Post »

I just reported this bug on Connect :

.NET 4.0 supports covariance and contravariance in delegates and interfaces. Unfortunately, C++/CLI does not support this as of VC++ 2010 RTM. Considering that the most popular use for C++/CLI today is as an interop language, the compiler not supporting a feature that’s going to be heavily used in the BCL and in new C# libraries is a very serious problem. It will impose limits on how effective C++/CLI will be as an interop-language.

If you think this is a serious enough problem, please vote the bug up so it gets more attention. Thank you.

Read Full Post »

The lack of intellisense has been the biggest show-stopper for using VC++ 2010 for any managed or mixed mode programming. Many people could not make the upgrade from VC++ 2008 for this very reason. Fortunately, the latest version of Visual Assist X from Whole Tomato Software provides fully functional intellisense for C++/CLI code! VA has always been a truly impressive add-in for VC++ users for a decade or so now, and with this update they make it obvious why they are still one of the most popular and most useful add-ins for Visual C++.

For anyone doing C++/CLI in VS 2010 and totally frustrated with the Notepad like editing experience, or for anyone holding off on upgrading to VS 2010, I strongly recommend Visual Assist X. I’ve been using it for a couple of weeks now and I have not noticed any performance issues with VS 2010 although I am on a very fast machine with heaps of memory. That said, there are several other improvements and refactoring features that Visual Assist X provides but I was primarily evaluating it for the C++/CLI intellisense.

Read Full Post »

A month or two back, I had to write a launcher app that would allow/disallow the running of select installers based on various conditions and config files. Since this would run prior to any of the MSIs, and thus couldn’t assume the presence of any dependencies like .NET or the VC++ runtime, I wrote it as a statically linked MFC dialog app using VC++ 2008. All was well with initial testing. But during a final testing phase, the launcher failed to run on a fresh Windows 2000 box with an error about a missing gdiplus.dll.

Windows XP and later OSes like Vista and Windows 7 have GDI+ by default though you may need to apply patches for the latest updates on XP. Windows 2000 predates GDI+ and thus does not have GDI+ by default though a redistributable is available as a separate download. So that’s why it failed. But why is there a dependency at all? I had always assumed that a statically linked MFC app would run anywhere. The it struck me – the BCG stuff that they added to MFC starting VC++ 2008! That code used GDI+ and thus had a GDI+ dependency.

Obviously I couldn’t include the GDI+ redistributable for the launcher app and I didn’t want to remotely take the risk of manually copying along the GDI+ DLL (or any extra files it needs) what with the various updates out there. Eventually, I rewrote the app as a plain Win32 API dialog app (the app was kinda simple, so it didn’t take me too long). I know not many people support Windows 2000 today, but some of our clients are still on that OS, and so it was important for us to support it. Anyway, this is just something to keep in mind when using MFC to write a stub executable that should run anywhere.

Read Full Post »

This one’s an obvious error really – but it’s still undocumented, and thus qualifies for a blog entry. I guess once __arglist was dropped from the standard documentation, all its associated error messages were dropped too.

Compiler Error CS0226

Error Message

An __arglist expression may only appear inside of a call or new expression

Example

The following sample generates CS0226

// error CS0226
__arglist("apples", "pears");

Expected usage
static void Foo(Object obj, __arglist)
{
    Console.WriteLine("First arg : {0}", obj);

    ArgIterator iterator = new ArgIterator(__arglist);
    for (int i = iterator.GetRemainingCount(); i > 0; i--)
    {
        Console.WriteLine(TypedReference.ToObject(iterator.GetNextArg()));
    }
}

. . .

Foo(x, __arglist("apples", "pears"));

Read Full Post »

There was a very interesting thread on Code Project’s C++/CLI forum last week. Here’s the link to the thread :

The gist of the post is that the C++/CLI compiler was not recognizing an overloaded unary operator defined in an interface while it could do so when the interface was changed to a base class.

Here’s some example code that reproduces the problem :

 interface class Base
 {
 public:
  static int operator * (Base^) { return 99; }
  static int operator + (Base^) { return 99; }
 };

 ref class Derived : Base
 {
 };

  static void Foo()
  {
    Derived^ d = gcnew Derived();

    int x = *d;
    int y = +d; 

Both those lines will not compile. In the case of the * operator you get a confusing error because the compiler assumes you are trying to dereference the handle.

Error 1 error C2440: 'initializing' : cannot convert from
    'Test::Derived' to 'int'
Error 2 error C2675: unary '+' : 'Test::Derived ^' does not define this
    operator or a conversion to a type acceptable to the predefined
    operator

Changing Base from an interface class to a ref class works fine. I believe this is a compiler bug because the ECMA language specification says this in section 25.2 Interface members:

“An interface definition can declare zero or more members. The members of an interface shall be static data members, instance or static functions, a static constructor, instance or static properties, instance or static events, operator functions, or nested types of any kind. An interface shall not contain instance data members, instance constructors, or a finalizer.”

The workaround right now is to do this :

int x = Base::operator *(d);
int y = Base::operator +(d);
Affected versions:

This bug exists in VS 2008 as well as in VS 2010 RC.

Read Full Post »

In my last blog entry I had shown a WWS native client connecting to a WCF service. In this one I’ll talk about how the WCF service can be converted into an equivalent WWS service. Connecting clients (whether WWS, WCF, or other) would continue to behave the same. I am going to use the same c/h files that wsutil generated from the wsdl file. There is a function signature generated for us to match the service contract methods. In our case there’s just one – WSHttpBinding_IStringService_ReverseCallback. So the first thing is to add a method that matches this signature, and this will reverse a string just like the WCF service (except we write it in C or C++).

HRESULT CALLBACK Reverse(
	__in const WS_OPERATION_CONTEXT* context,
	__in WCHAR* s,
	__out  WCHAR** reverse,
	__in_opt const WS_ASYNC_CONTEXT* asyncContext,
	__in_opt WS_ERROR* error)
{
	WS_HEAP* heap = NULL;

	HRESULT hr = WsGetOperationContextProperty(
		context,
		WS_OPERATION_CONTEXT_PROPERTY_HEAP,
		&heap,
		sizeof(heap),
		error);

	if (FAILED(hr))
	{
		return hr;
	}

	hr = WsAlloc(
           heap,
           sizeof(WCHAR) * (wcslen(s) + 1),
           (void**)reverse,
           error);

	if (FAILED(hr))
	{
		return hr;
	}

	wcscpy(*reverse, s);
	wcsrev(*reverse);

	return ERROR_SUCCESS;
}

I first use WsGetOperationContextProperty to get the heap and then use WsAlloc to allocate memory for the reversed string on this heap. We do not ever allocate memory using standard memory allocation mechanisms unless it’s memory we will have the option to delete/free when we are done using it. Instead we use the WWS heap which frees us from worrying about memory leaks – the memory will be released when the heap is reset or freed.

Now let’s get to creating the service. Again, I will not show the error handling code (to save space) but every HRESULT return value must be checked for success before proceeding further. The first thing is to create the error and heap objects just as we did when writing the WWS client.

WS_ERROR* error = NULL;
HRESULT hr = WsCreateError( NULL, 0, &error);
if (FAILED(hr))
{
 // ...
}

WS_HEAP* heap = NULL;
hr = WsCreateHeap( 100000, 0, NULL, 0, &heap, error);
if (FAILED(hr))
{
 // ...
}

The next step is to create a service endpoint.

WSHttpBinding_IStringServiceFunctionTable functions = { Reverse };

WS_STRING url = WS_STRING_VALUE(L"http://localhost:8000/StringService");

WS_HTTP_BINDING_TEMPLATE templateValue = {};

WS_SERVICE_ENDPOINT* serviceEndpoint;
hr = WSHttpBinding_IStringService_CreateServiceEndpoint(&templateValue,
    &url, &functions, NULL, NULL, 0,
    heap, &serviceEndpoint, error);
if (FAILED(hr))
{
  // ...
}

Notice how we use the generated WSHttpBinding_IStringServiceFunctionTable to specify the list of functions (just one in our case). Now I use the proxy WSHttpBinding_IStringService_CreateServiceEndpoint to create the end point (and it internally calls WsCreateServiceEndpointFromTemplate). I have used default values for other arguments, but there is a lot of custom configuration that can be done. We’ll now create the service host:

WS_SERVICE_HOST* host;
const WS_SERVICE_ENDPOINT* serviceEndpoints[1];
serviceEndpoints[0]= serviceEndpoint;
hr = WsCreateServiceHost( serviceEndpoints, 1,
    NULL, 0,  &host, error);
if (FAILED(hr))
{
}

We only have one endpoint, but the service host can host multiple endpoints. While I have called WsCreateServiceHost with default arguments (basically passing NULL) it’s possible to set various service properties at this point. The last step is to open the service host.

hr = WsOpenServiceHost(host, NULL, error);

The above code will open the service and start listening on each of the endpoints (just one in our example). For a test console app, use a _getch() so the app won’t exit. Once the app’s done, close and free the service host :

WsCloseServiceHost(host, NULL, error);
WsFreeServiceHost(host);

And also free the heap/error objects :

if (heap)
{
  WsFreeHeap(heap);
}

if (error)
{
  WsFreeError(error);
}

You can now run the service and the WWS client from the last blog entry will connect to it and invoke the reverse function successfully. You can even write a simple WCF client and it’ll connect to this just as if this was a WCF service. I do agree that all these proxies, having to create/free structures, handling HRESULTs etc. may seem a tad foreign if you are coming from a pure C# or VB.NET world. But if you are not put off by C++, and keeping your service or client code native is important to you, then WWS sure seems to be a great way to do it. I do intend to research into WWS a little more in detail, so expect more blog entries and an article or two on the topic in future.

Read Full Post »

I have been meaning to play with Windows Web Services ever since I heard Nikola Dudar talk about it at the MVP Summit earlier this year. It’s natively included with Windows 7, but can also be installed and used from older OSes (XP, Vista, 2003 and 2008). You can write native clients using WWS that can connect to a WCF service, and similarly you can write a WWS native service that can be consumed by a WCF client. It’s so compatible that you can replace either a WCF client or a WCF service with a WWS equivalent without the other party being aware of it.

One of the first things I did was write a very simple WCF service and then connected to it using a simple WWS client. I intend to write a detailed article on that in the next few days but I’ll go through the basic steps in this blog so I can use that as some basic raw material for my article.

The first thing I did was to create a very simple WCF service. Here’s the service interface :

    [ServiceContract]
    interface IStringService
    {
        [OperationContract]
        string Reverse(string s);
    }

    class MyStringService : IStringService
    {
        public string Reverse(string s)
        {
            return new string(s.Reverse().ToArray());
        }
    }

Here’s some slightly stripped out code that shows how the service is created and run.

WSHttpBinding binding = new WSHttpBinding();

// .. set properties on binding

Uri baseAddress = new Uri("http://localhost:8000/StringService");

using (ServiceHost serviceHost = new ServiceHost(
  typeof(MyStringService), baseAddress))
{
    ServiceMetadataBehavior smb =
      serviceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
    if (smb == null)
        smb = new ServiceMetadataBehavior();

    // .. set properties on smb

    serviceHost.AddServiceEndpoint(
      ServiceMetadataBehavior.MexContractName,
      MetadataExchangeBindings.CreateMexHttpBinding(),
      "mex"
    );

    serviceHost.AddServiceEndpoint(
      typeof(IStringService), binding, baseAddress);
    serviceHost.Open();

Now there are two steps to do before we start writing the WWS native client :

  1. Use svcutil to generate WSDL from the WCF service
  2. Use the Windows WebServices compiler tool (wsutil) to generate proxies (c/h files).

Once you do this, create a native C++ console project, add the c/h files (and remember to disable precompiled headers for the C files). I am not going to show error handling code in the below code, but you need to check the HRESULT for error/success after every call. First thing is to declare some variables and also specify the service URL :

HRESULT hr = ERROR_SUCCESS;
WS_ERROR* error = NULL;
WS_HEAP* heap = NULL;
WS_SERVICE_PROXY* proxy = NULL;

WS_ENDPOINT_ADDRESS address = {};
WS_STRING url= WS_STRING_VALUE(L"http://localhost:8000/StringService");
address.url = url;

WS_STRING is a simple struct that has a WCHAR* (that will point to the string) and a ULONG that will represent the length. I’ve used the WS_STRING_VALUE macro to initialize the string there.

The WWS APIs provide rich error info through the WS_ERROR structure and so we create a WS_ERROR struct using the WsCreateError API call (using default arguments).

hr = WsCreateError(NULL,  0,  &error);
if (FAILED(hr))
{
  //...
}

We also need to create a WS_HEAP object which represents an opaque heap structure (error handling not shown) :

hr = WsCreateHeap(2048, 512, NULL, 0, &heap, error); 

The next step is to create the service proxy :

WS_HTTP_BINDING_TEMPLATE templ = {};
hr = WSHttpBinding_IStringService_CreateServiceProxy(&templ, NULL, 0, &proxy, error);

WSHttpBinding_IStringService_CreateServiceProxy is a proxy function that was generated by wsutil. Internally it calls the WWS API WsCreateServiceProxyFromTemplate but it saves us the hassle of correctly and properly filling up the various arguments. Now, we open the service proxy (connects us to the service endpoint) :

hr = WsOpenServiceProxy(proxy, &address, NULL, error);

At this point we are ready to make calls into the service for which we again use the proxy functions that are generated by wsutil.

WCHAR* result;

hr = WSHttpBinding_IStringService_Reverse(
        proxy, L"Nishant Sivakumar", &result,
        heap, NULL, 0, NULL, error);

if (FAILED(hr))
{
  // ...
}

wprintf(L"%s\n", result);

WSHttpBinding_IStringService_Reverse is generated for us and is a pretty simple function to use, and it internally wraps the call to the WsCall WWS API function, including correctly wrapping up all the arguments and the return value. Well, that’s pretty much it. Once you are done, just call all the close/free APIs :

if (proxy)
{
  WsCloseServiceProxy(proxy, NULL, NULL);
  WsFreeServiceProxy(proxy);
}

if (heap)
{
  WsFreeHeap(heap);
}

if (error)
{
  WsFreeError(error);
}

I was absolutely thrilled when I ran the console app and it successfully connected to the WCF service. The native client is about twice as long (number of lines of code) as an equivalent managed WCF client would have been but that’s a small price to pay for the ability to consume a WCF service in pure native code. In a later blog entry I will write about how the WCF service itself can be replaced with an identical WWS service (both WCF and WWS clients will continue to work the same).

Read Full Post »

In VS 2010, Tools/Options does not have a VC++ directories tab (where you normally set the include/lib search folders). Instead if you take project settings for a C++ project, you’ll see VC++ Directories listed under Configuration Properties. Of course these are per project and not per user (as in VS 2008). If you want to change it for the current user globally, bring up the Property Manager and then you’ll see various property sheets under Debug and Release (there may be more configurations on your machine). Just edit the property sheet named Microsoft.Cpp.Win32.user and now you’ll have set it globally for your user for that specific configuration.

Read Full Post »

Older Posts »

Follow

Get every new post delivered to your Inbox.