Click to Rate and Give Feedback
Related Articles

There's always been disagreement about whether large blobs, such as document and multimedia items, should be stored in the database or file system. In SQL Server 2008 you don't have to choose; filestream storage provides the best of both approaches.

Bob Beauchemin

MSDN Magazine May 2009

...

Read more!

Memory usage can have a direct impact on how fast an application executes and thus is important to optimize. In this article we discuss the basics of memory optimization for .NET programs.

Subramanian Ramaswamy and Vance Morrison

MSDN Magazine June 2009

...

Read more!

In this column, the author lays out some guiding principles that you should follow when working with the ASP.NET MVC framework.

Matt Ellis

MSDN Magazine July 2009

...

Read more!

Udi Dahan explains how his team identified and overcame unforeseen problems while developing a large-scale software + services trading application.

Udi Dahan

MSDN Magazine April 2009

...

Read more!

Here the author dissects the ASP.NET MVC framework and looks at how controllers work. He then explains how the framework interacts with your controllers and how you can influence those interactions.

Scott Allen

MSDN Magazine May 2009

...

Read more!

Also by this Author

Paul DiLascia

MSDN Magazine April 2006

...

Read more!

This month DLL problems, context menus, MFC strings to managed C++, and more.

Paul DiLascia

MSDN Magazine October 2006

...

Read more!

Paul DiLascia

MSDN Magazine May 2005

...

Read more!

Paul DiLascia

MSDN Magazine July 2005

...

Read more!

By now you're probably used to reaching into the .NET Framework using Managed Extensions with your C++ code. But what do you do if you have legacy apps that use older versions of the compiler, or if you want to avoid some of the CLR requirements? Well, you can wrap Framework classes in a native way so you can use them in any C++/MFC app without /clr. Paul DiLascia shows you how.

Paul DiLascia

MSDN Magazine April 2005

...

Read more!

Popular Articles

The MVP pattern helps you separate your logic and keep your UI layer free of clutter. This month learn how.

Jean-Paul Boodhoo

MSDN Magazine August 2006

...

Read more!

Jeff Prosise explains when it's better to use UpdatePanel and when it's better to use asynchronous calls to WebMethods or page methods instead.

Jeff Prosise

MSDN Magazine June 2007

...

Read more!

Now you can perform efficient, sophisticated text analysis using regular expressions in SQL Server 2005.

David Banister

MSDN Magazine February 2007

...

Read more!

When incorporating the ASP.NET DataGrid control into your Web apps, common operations such as paging, sorting, editing, and deleting data require more effort than you might like to expend. But all that is about to change. The GridView control--the successor to the DataGrid-- extends the DataGrid's functionality it in a number of ways. First, it fully supports data source components and can automatically handle data operations, such as paging, sorting, and editing, as long as its bound data source object supports these capabilities. In addition, ...

Read more!

WPF is one of the most important new technologies in the .NET Framework 3.0. This month John Papa introduces its data binding capabilities.

John Papa

MSDN Magazine December 2007

...

Read more!

C++ Q&A
Singleton Class Private Constructor, C# Singleton Class, and More
Paul DiLascia

Code download available at: CQA0302.exe (40 KB)
Browse the Code Online

QI have a C++ singleton class, and I have done the preliminaries of making the constructor private. I wrote a static function that returns a reference to the one and only object, restricting all means of creating the object except the following:
// This should not compile 
CSingleton temp = CSingleton::GetObjectInstance();
How can I prevent this line from compiling?
QI have a C++ singleton class, and I have done the preliminaries of making the constructor private. I wrote a static function that returns a reference to the one and only object, restricting all means of creating the object except the following:
// This should not compile 
CSingleton temp = CSingleton::GetObjectInstance();
How can I prevent this line from compiling?
Nilesh Prakash Padbidri

AWhen the C++ compiler encounters the statement
CSingleton temp = CSingleton::GetInstance();
it looks for a copy constructor, which is a constructor with the signature CSingleton(const CSingleton&). If you don't provide a copy constructor, C++ will provide one for you. The default copy constructor does a simple flat copy of the bytes from one object to the other. If you want something else, you'll have to implement your own copy constructor. In this case, to disallow copying, you can make it private.
class CSingleton {
private:
  // private copy constructor
  CSingleton(const CSingleton& obj) 
  { ASSERT(FALSE); } // should never happen
};
AWhen the C++ compiler encounters the statement
CSingleton temp = CSingleton::GetInstance();
it looks for a copy constructor, which is a constructor with the signature CSingleton(const CSingleton&). If you don't provide a copy constructor, C++ will provide one for you. The default copy constructor does a simple flat copy of the bytes from one object to the other. If you want something else, you'll have to implement your own copy constructor. In this case, to disallow copying, you can make it private.
class CSingleton {
private:
  // private copy constructor
  CSingleton(const CSingleton& obj) 
  { ASSERT(FALSE); } // should never happen
};
If you do this, you'll also have to implement the default (no-argument) constructor, if you haven't already, because C++ only generates a default constructor if no others are defined. Without the default constructor, you won't be able to instantiate the singleton. You can make the default constructor protected or private, depending on whether you want to let other classes derive from CSingleton. Figure 1 shows the details. So the short answer to your question is: implement a private copy constructor.
// This program illustrates how to write a singleton class (a class that
// can have only one instance) in C++. The trick is to make the default
// constructor, copy constructor and assignment operator all private. A
// static function GetInstance returns the one and only object instance.
//
// If you attempt to compile this program, it will generate errors.
// (See main function below.)
// 
class CSingleton {
public:
   static CSingleton& GetInstance() {
      static CSingleton theInstance; // one and only instance
      return theInstance;
   }

protected:
   // need default ctor for GetInstance.
   // ctor is protected, not private in case you want to derive.
   CSingleton() { }

private:
   CSingleton(const CSingleton& o) { }
   CSingleton& operator=(const CSingleton& o) { }
};
 
main()
{
    // These lines will not compile:
    CSingleton x = CSingleton::GetInstance(); // error: private 
                                              // copy ctor!
    CSingleton y = CSingleton::GetInstance(); // error: private 
                                              // copy ctor!
    x = y;                                    // error: private 
                                              // assignment!
}

QI've been programming in C++ for a long time, and I'm familiar with a number of patterns like the singleton (a global object with a private constructor). Now I'm starting a project in C# using Microsoft® .NET and I'd like to know the best way to create a singleton class in C#.
QI've been programming in C++ for a long time, and I'm familiar with a number of patterns like the singleton (a global object with a private constructor). Now I'm starting a project in C# using Microsoft® .NET and I'd like to know the best way to create a singleton class in C#.
Marianne Simone

ASingleton classes are even easier in C# than they are in C++ because the .NET Framework has the notion of singletons built in. Here's the C# Singleton pattern distilled:
sealed class Singleton
{
  private Singleton() { }
  public static readonly Singleton 
    TheInstance = new Singleton();
}
ASingleton classes are even easier in C# than they are in C++ because the .NET Framework has the notion of singletons built in. Here's the C# Singleton pattern distilled:
sealed class Singleton
{
  private Singleton() { }
  public static readonly Singleton 
    TheInstance = new Singleton();
}
As in C++, you can use a private constructor to prevent programmers from creating instances of Singleton. To prohibit inheritance, declare your class sealed. (In C++ you can do this by making all constructors private.) Instead of a static object inside a static GetInstance function, as shown in Figure 1, C# lets you create a read-only static property (in this case, Singleton.TheInstance) initialized to a new instance of the class. This accomplishes the same thing as the C++ pattern with less typing: the framework won't actually create and initialize TheInstance until someone attempts to use it, which you can do like so:
Singleton s = Singleton.TheInstance;
The framework even takes care of synchronization problems that can arise in multithreaded situations. Figure 2 shows a C# Singleton you can actually compile and run. For more on singletons, see the article titled "Exploring the Singleton Design Pattern" in the MSDN® library.
// Singleton — list top-level visible windows
//
using System;

sealed class Singleton
{
   private Singleton() { }
   public static readonly Singleton TheInstance = new Singleton();
   public void SayHello() {
      Console.WriteLine("hello,world");
   }
}

class MyApp {
   // global command-line switches

   [STAThread]
   // main entry point
   static int Main(string[] args) {
//    Singleton s = new Singleton(); // error!
      Singleton s = Singleton.TheInstance;
      s.SayHello();
      return 0;
   }
}

QI read your column in the August 2002 issue of MSDN Magazine and found it very helpful. My problem is similar to your delegates example. I pass a C# delegate into unmanaged C++, and C++ makes the callback whenever it needs to. However, one of the members in the signature of the callback is an int array, and when it does get back into C#-land, C# thinks the array is of length one and only contains the first member of the array, no matter how big the array is. I've looked through many books and Web sites, but not many give help on interop issues between C# and unmanaged C++. I would be grateful if you could give me some ideas.
QI read your column in the August 2002 issue of MSDN Magazine and found it very helpful. My problem is similar to your delegates example. I pass a C# delegate into unmanaged C++, and C++ makes the callback whenever it needs to. However, one of the members in the signature of the callback is an int array, and when it does get back into C#-land, C# thinks the array is of length one and only contains the first member of the array, no matter how big the array is. I've looked through many books and Web sites, but not many give help on interop issues between C# and unmanaged C++. I would be grateful if you could give me some ideas.
Vince Kwok

AWhile Microsoft .NET makes mixing managed and unmanaged code as painless as possible, the finer details of interop can sometimes be intimidating and elusive. But the designers were actually quite thorough in this area, so when it comes to interop, it's usually safe to assume that if you can't make things work, it's because you haven't yet divined the magic voodoo. Life can be even more confusing when callbacks are involved because of the added indirection. Even certified C++ gurus sometimes have to scratch their heads to recall the proper typedef syntax for callbacks. Never fear, I'm here to help.
AWhile Microsoft .NET makes mixing managed and unmanaged code as painless as possible, the finer details of interop can sometimes be intimidating and elusive. But the designers were actually quite thorough in this area, so when it comes to interop, it's usually safe to assume that if you can't make things work, it's because you haven't yet divined the magic voodoo. Life can be even more confusing when callbacks are involved because of the added indirection. Even certified C++ gurus sometimes have to scratch their heads to recall the proper typedef syntax for callbacks. Never fear, I'm here to help.
I wrote a little program called TestArray that shows how to pass int arrays between managed and unmanaged code in a variety of situations. TestArray actually comprises two pieces: an unmanaged DLL (MyLib.dll) written in C++ and a .NET-centric console application written in C#. Figure 3 shows the code and makefile; Figure 4 shows its results. TestArray runs three tests. The first passes a .NET Array of ints from C# to an unmanaged C function, ArrayTest in MyLib.dll:
extern "C" __declspec( dllexport )
int ArrayTest(int ar[], int count)
{
  ••• // printf to print the array
  return count;
}


MyLib.cpp
// To build:
//
//    cl /LD MyLib.cpp
//
#include <stdio.h>

// This is normally defined in windows.h:
#define CALLBACK __stdcall

// callback function takes array of ints and length
typedef void (CALLBACK* ARRAYCB)(int ar[], int len);

// fwd ref
static void PrintArray(int* ar, int len);

///////////////////
// Simple array test: unmanaged C function receives array, length and
// displays it on console.
//
extern "C" __declspec( dllexport ) void TestArray(int ar[], int len)
{
   // display array on stdout
   printf(" [c++] inside TestArray: ar=");
   PrintArray(ar, len);
}

///////////////////
// Callback test: unmanaged C function receives a callback that takes an
// array and count.
//
extern "C" __declspec( dllexport ) void TestArrayCallback(ARRAYCB cbfn)
{
   // create an array
   int len = 10;
   int* parray = new int[len];
   for (int i=0; i<len; i++) {
      parray[i] = len-i;
   }

   // pass it to callback
   printf(" [c++] inside TestArrayCallback, cbfn=%p, calling it 
      now...\n", cbfn);
   (*cbfn)(parray, len);
}

///////////////////
// Modify array test: unmanaged C function receives an array, modifies
// it, and returns to .NET caller. The array must be passed as a C# ref,
// so it's declared here as a ptr-to-array. The length is also passed as
// ref so it's a ptr-to-int. The function replaces each item in the
// array with its value squared. Its function doesn't alter the size of
// the array, but it could. 
//
extern "C" __declspec( dllexport ) void TestModifyArray(int** pArray, 
   int* pLen)
{
   int len = *pLen;
   int* ar = *pArray;
   
   printf(" [c++] inside TestModifyArray, *pArray=");
   PrintArray(ar, len);
   printf(" [c++] squaring elements...\n");

   // modify array: square each element
   for (int i=0; i<len; i++) {
      ar[i] *= ar[i];
   }
}

//////////////////
// Helper fn to print array on stdout.
//
static void PrintArray(int* ar, int len)
{
   printf("[");
   for (int i=0; i<len; i++) {
      if (i>0)
         printf(",");
      printf("%d", ar[i]);
   }
   printf("], len=%d\n", len);
}
TestArray.cs
// This program illustrates how to pass integer arrays between C# and
// C++ in various ways, and in particular how to pass an array from C++
// to a C# callback without having the array length collapse to 1. The
// trick is to use MarshalAs with SizeParamIndex to tell the framework
// which callback parameter contains the array size.
//
// To build:
//
//    csc TestArray.cs 
//
using System;
using System.Runtime.InteropServices;

//////////////////
// This class wraps the unmanaged C++ functions in MyLib.dll.
//
class LibWrap {
   [DllImport("MyLib.dll")]
   public static extern void TestArray(int[] ar, int len);

   // callback delegate declaration. SizeParamIndex = 1 tells .NET that
   // the length of the array is in the 1st (2nd from 0-offset) param.
   //
   public delegate void ArrayCB(
      [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] int[] ar, int
         len);

   [DllImport("MyLib.dll")]
   public static extern void TestArrayCallback(ArrayCB cb); 

   [DllImport("MyLib.dll")]
   public static extern void TestModifyArray( ref IntPtr array, ref 
      int len );
}
//////////////////
// App class with Main entry
//
class MyApp {

   // callback function simply displays array contents
   private static void MyCallbackFn(int[] ar, int len) {
      Console.Write(" [c# ] inside MyCallbackFn with array=");
      WriteArray(ar);
   }

   // main entry point
   [STAThread]
   static int Main(string[] args) {

      // create array
      int len = 7;
      int[] array = new int[len];
      for (int i=0; i<len; i++) {
         array[i] = i+1;
      }

      // Run simple array test.
      Console.WriteLine("TEST 1 — Pass array from .NET to C++");
      Console.Write(" [c# ] calling TestArray with array=");
      WriteArray(array);
      LibWrap.TestArray(array, len);

      // Run callback test
      Console.WriteLine("\nTEST 2 — Pass array callback from .NET
                        to C++:");
      Console.WriteLine(" [c# ] calling TestArrayCallback...");
      LibWrap.ArrayCB mycb = new LibWrap.ArrayCB(MyCallbackFn);
      LibWrap.TestArrayCallback(mycb);

      // Run modify array test. This requires copying the array to an
      // InPtr buffer allocated with Marshal.AllocCoTaskMem.
      // 
      Console.WriteLine("\nTEST 3 — Pass modifiable array from .NET 
                        to C++");
      IntPtr buf =
         Marshal.AllocCoTaskMem(Marshal.SizeOf(array[0]) * array.Length);
      Marshal.Copy(array, 0, buf, array.Length );
      Console.Write(" [c# ] calling TestModifyArray with array=");
      WriteArray(array);
      LibWrap.TestModifyArray(ref buf, ref len); // call DLL
      array = new int[len];                  // new array w/returned length 
      Marshal.Copy(buf, array, 0, len);      // copy buffer to array
      Marshal.FreeCoTaskMem(buf);            // free buffer
      Console.Write(" [c# ] TestModifyArray returns array=");
      WriteArray(array);

      return 0;
   }

   // helper to print array on console
   static private void WriteArray(int[] ar)
   {
      Console.Write("[");
      for (int i=0; i<ar.Length; i++) {
         if (i>0) 
            Console.Write(",");
         Console.Write(ar[i]);
      }
      Console.WriteLine("], len={0}", ar.Length);
   }
makefile
################################################################
# MSDN Magazine — February 2003
# If this code works, it was written by Paul DiLascia.
# If not, I don't know who wrote it.
# Compiles with Visual Studio .NET on Windows XP. Tab size=3.
#
# To build, type "NMAKE" in a console window. Make sure your LIB and
# INCLUDE variables are set up as per the Visual Studio vsvars32.bat.
#

all: MyLib.dll TestArray.exe

MyLib.dll: MyLib.cpp
   cl /LD MyLib.cpp

TestArray.exe: MyLib.dll TestArray.cs
   csc TestArray.cs
TestArray takes an ordinary C array of ints and its length and displays them on stdout. Extern "C" is required to suppress C++ name-mangling and __declspec(dllexport) exports the function. This is C 101; MyLib.dll could have been written 10 years ago.
To make TestArray known to C#, you have to wrap it the .NET interop way, like this:
using System.Runtime.InteropServices;
class LibWrap {
  [DllImport("MyLib.dll")]
  public static extern void TestArray(int[] 
      ar, int len);
}
Now you can call TestArray with a .NET Array and the framework will automagically marshal it properly:
int[] array = // create, initialize
LibWrap.TestArray(array, array.Length);
The interop services in the common language runtime (CLR) convert the .NET Array into a C array of ints. Remember, in .NET an array is not a block of memory stuffed with ints one after another, as in C. In .NET, System.Array is a full-blown class with rank, length, and lower bound, as well as data. To pass the length to C++, you simply pass Array.Length as a separate parameter.
But what about going the other way? That is, from unmanaged to managed code. In particular, how can you pass an array to a callback method? The second test shows how. This is where life gets a little tricky because if you declare your callback parameter as int[], you'll discover, as did Vince, that the array arrives with a length of 1 every time. C-style arrays don't have their lengths built in, whereas .NET Arrays do. So how do you tell .NET the array length when going from C++ to C#? The answer lies in the magic MarshalAs attribute and special field SizeParamIndex:
class LibWrap {
  public delegate void ArrayCB(
    [MarshalAs(UnmanagedType.LPArray, 
      SizeParamIndex=1)] int[] ar, int len);
}
In general, MarshalAs lets you tell .NET how to marshal parameters when you don't like the default. Here, marshaling as LPArray (C-style array) is fine, but you need SizeParamIndex set to 1 to tell .NET that the length is the second parameter (the zero-based index is 1). If you have a fixed-length array, you can use SizeConst to specify a fixed size—for example, SizeConst = 50 if the array always has 50 elements. You only need SizeParamIndex in the delegate declaration, not the actual callback:
// don't need MarshalAs here
private static void MyCallbackFn(int[] ar, int len) {
  // ... ar.Length is same as len
}
The C++ side of things is straightforward. The only challenge is remembering how to declare a pointer-to-function in C. Here it is:
// ptr-to-fn
typedef void (*ARRAYCB)(int ar[], int len);
So now the C function that runs the callback test looks like this:
extern "C" __declspec( dllexport ) 
void TestArrayCallback(ARRAYCB cbfn)
{
  int len =    // length of array
  int* array = // create, initialize
  (*cbfn)(array, len); // call it
}
Now if you write the following lines everything works fine, courtesy of .NET:
LibWrap.ArrayCB mycb = new LibWrap.ArrayCB(MyCallbackFn);
LibWrap.TestArrayCallback(mycb);
When TestArrayCallback calls cbfn, the interop services convert the C-style array into a .NET Array upon arrival, with Array.Length set to whatever you pass as the len parameter. Amazing! To see for yourself, download the code, compile, and go (for full source code, see the link at the top of this article). So the short answer to your question is: you must declare the array parameter of your delegate with MarshalAs and SizeParamIndex equal to the index of the parameter that holds the size.
I've answered Vince's question, but there's one more situation I should mention briefly before saying bye-bye for today. The first test shows how to pass an array from C# to C++, and the second test shows how to pass an array the other way through a callback. Curious minds might wonder if you can pass an array from managed to unmanaged code in a way that lets the unmanaged code modify the array directly. In fact, you can, and that's what the third test in my sample program does.
You might think all you have to do is declare and pass the array as a reference (ref), which makes sense but, alas, doesn't work. If you try, you'll discover the array goes from C# to C++ just fine, but always comes back with the length set to 1. Sigh. So then you might think to try the SizeParamIndex trick again, but this time the compiler complains, muttering something like, "can't use SizeParamIndex with reference array..." Double sigh.
So how can you pass a modifiable array from managed to unmanaged code? TestArray shows the way: you must pass the array as an IntPtr. This requires manually copying the array to and from a buffer that you previously allocate with Marshal.AllocCoTaskMem. It's ugly—but hey, it works! Figure 3 shows the gory details.
Like I said at the outset, the .NET interop services have everything you need to marshal all kinds of parameters any way you like. For more details see "Default Marshaling Behavior" and in particular, "Default Marshaling for Arrays" in the .NET documentation. And make sure to bring along your universal nerdspeak de-crypto translator!
Minor correction: In my recent article, ".NET GUI Bliss," which appeared in the November 2002 issue, I stated that "XUL was developed by the Java language folks for Mozilla." While there are no doubt many Java folks who've contributed to XUL, XUL is, properly speaking, a Mozilla effort. Sorry for the confusion.

Send your questions and comments for Paul to  cppqa@microsoft.com.


Paul DiLasciais a freelance writer, consultant, and Web/UI designer-at-large. He is the author of Windows++: Writing Reusable Windows Code in C++ (Addison-Wesley, 1992). Paul can be reached at askpd@pobox.com or http://www.dilascia.com.

Page view tracker