.Net and Legacy Code

As you can see from my previous post I am interested in recycling my old “C” code for use in .Net. I don’t want to rewrite the code in C# or VB so I am wrapping it with a C# DLL. The good thing about .Net is that it already has much of the functionality that I put into some of these old C libraries. However, there is a lot that I didn’t write that I would like to wrap, in particular: GSL gets wrapped here: Gnu.dll.

One of the big problems I have had with wrapping old DLLs is with arrays. .Net managed arrays are quite different from C arrays. Consider the following from GSL:
// double gsl_stats_mean (const double data[]
// , const size_t stride
// , const size_t n);
exact spelling=true,
CharSet = CharSet.Ansi,
public static extern double mean
( [In] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)]
double [] data
, [In] int stride
, [In] int n);

It seems to work OK, so what’s the problem? Try using this on a bunch of 1,000,000 element arrays and see what happens to the resources on your PC and you’ll soon see!

The MarshalAs class copies the data in the .Net array into a new C array. Here is a better implementation that uses the GCHandle:

public class gsl_stats {
internal static unsafe GCHandle _gch_pinned_ptr(double[] data, ref double *p)
	GCHandle gch = GCHandle.Alloc(data, GCHandleType.Pinned);
	IntPtr ip = gch.AddrOfPinnedObject();
	p = (double*)ip.ToPointer();
	return gch;
public unsafe static double mean (double [] data
	, int stride, int n)
double *p = null;
	GCHandle gch = _gsl._gch_pinned_ptr(data, ref p);
	double d = gsl_stats_DLL.mean(p, stride, n);
	return d;
} // mean()
} // gsl_stats
public class gsl_stats_Dll
	, ExactSpelling=true
	, CharSet = CharSet.Ansi
	, CallingConvention=CallingConvention.Cdecl
	, EntryPoint="gsl_stats_mean")]
	public static extern unsafe double mean
		( [In] double *data, [In] int stride, [In] int n);
} // gsl_stats_DLL 

Leave a Reply

You must be logged in to post a comment.