Build Action: LinkResource

Jun 10, 2011 at 12:32 PM

In project Microsoft.Research.Science.Data.NetCDF4, I can enable LinkResource Build Action on all contained files. However, I can not see this build action in my other projects?

Jun 10, 2011 at 12:37 PM

Because I wanna use NetCDF without SDS in C#. I copied those code from SDS to try using solely NetCDF.

 class Program
    {
        static void Main(string[] args)
        {
            int i;
            string path = @"C:\data_11.nc";
            NetCDFInterop.nc_create(MarshalString(path), (int)CreateMode.NC_NETCDF4, out i);
            NetCDFInterop.nc_redef(i);
            NetCDFInterop.nc_put_att_string(i, -1, MarshalString("history"), new IntPtr(1), MarshalStringArray(new String[] { "his" }));
            NetCDFInterop.nc_enddef(i);
            NetCDFInterop.nc_sync(i);
            NetCDFInterop.nc_close(i);
            NetCDFInterop.nc_open(@"C:\data_11.nc", CreateMode.NC_WRITE, out i);
            NetCDFInterop.nc_close(i);
        }

        public static IntPtr MarshalString(string str)
        {
            byte[] array = Encoding.UTF8.GetBytes(str);
            int size = Marshal.SizeOf(typeof(byte)) * (array.Length + 1);
            IntPtr ptr = Marshal.AllocHGlobal(size);
            Marshal.Copy(array, 0, ptr, array.Length);
            Marshal.WriteByte(ptr, array.Length, 0);
            return ptr;
        }

        public static IntPtr MarshalStringArray(string[] strArr)
        {
            int n = strArr.Length;
            int sz = Marshal.SizeOf(typeof(byte*));
            IntPtr ptrA = Marshal.AllocHGlobal(sz * n);
            for (int i = 0; i < n; i++)
            {
                Marshal.WriteIntPtr(ptrA, sz * i, MarshalString(strArr[i]));
            }
            return ptrA;
        }
    }

    public enum CreateMode : int
    {
        NC_NOWRITE = 0,
        /// <summary>read &amp; write</summary>
        NC_WRITE = 0x0001,
        NC_CLOBBER = 0,
        /// <summary>Don't destroy existing file on create</summary>
        NC_NOCLOBBER = 0x0004,
        /// <summary>argument to ncsetfill to clear NC_NOFILL</summary>
        NC_FILL = 0,
        /// <summary>Don't fill data section an records</summary>
        NC_NOFILL = 0x0100,
        /// <summary>Use locking if available</summary>
        NC_LOCK = 0x0400,
        /// <summary>Share updates, limit cacheing</summary>
        NC_SHARE = 0x0800,
        NC_64BIT_OFFSET = 0x0200,
        /// <summary>Enforce strict netcdf-3 rules</summary>
        NC_CLASSIC = 0x0100,
        /// <summary>causes netCDF to create a HDF5/NetCDF-4 file</summary>
        NC_NETCDF4 = 0x1000
    }

    public static class NetCDFInterop
    {
        [DllImport("netcdf4.dll")]
        //public static extern int nc_create(string path, CreateMode cmode, out int ncidp);
        public static extern int nc_create(IntPtr path, int cmode, out int ncidp);

        [DllImport("netcdf4.dll")]
        public static extern int nc_open(string path, CreateMode omode, out int ncidp);
        [DllImport("netcdf4.dll")]
        public static extern int nc_close(int ncidp);
        [DllImport("netcdf4.dll")]
        public static extern int nc_sync(int ncid);
        [DllImport("netcdf4.dll")]
        public static extern int nc_enddef(int ncid);
        [DllImport("netcdf4.dll")]
        public static extern int nc_redef(int ncid);

        //[DllImport("netcdf4.dll")]
        //public static extern int nc_put_att_string(int ncid, int varid,
        //    [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]
        //    string name,
        //    IntPtr len,
        //    [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]
        //    String[] op);
        [DllImport("netcdf4.dll")]
        public static extern int nc_put_att_string(int ncid, int varid,
            IntPtr name,
            IntPtr len,
            IntPtr op);
    }

However, it does not work. Can you tell me how SDS is able to use NetCDF.DLL?

btw: Because I can not add NetCDF4.dll as LinkResource, I suspect this is the reason....

Jun 10, 2011 at 12:55 PM
chris_wen_11 wrote:

In project Microsoft.Research.Science.Data.NetCDF4, I can enable LinkResource Build Action on all contained files. However, I can not see this build action in my other projects?


LinkResource can be enabled only manually in the *.csproj file. To do this, use Unload command from the context menu on the project and then the Edit command to edit the project file as XML document.

Jun 10, 2011 at 1:00 PM
chris_wen_11 wrote:

Because I wanna use NetCDF without SDS in C#. I copied those code from SDS to try using solely NetCDF.

 ... 

However, it does not work. Can you tell me how SDS is able to use NetCDF.DLL?

btw: Because I can not add NetCDF4.dll as LinkResource, I suspect this is the reason....

Not clear, how it does not work. If you use your own netcdf.dll, probably, there is something wrong with it; for example, our netcdf4.dll has statically linked HDF5 and other libraries.

 

Jun 10, 2011 at 8:03 PM

In basis of your statement, I can not build the official NetCDF4.dll to work with SDS?

I tried to replace your netcdf4.dll with ours and it is possible to read data , while only writing data throws exception....I really feel confused...

What do you mean by other libraries? Do you associate additional libraries with netcdf4.dll?

I suspect that you also incoperate netcdf.h into netcdf4.dll?

 

Jun 11, 2011 at 8:34 AM

Netcdfl.dll requires HDF5.dll, zlib.dll and some others. If the netcdf.dll is built with dynamic linking of those libraries (as was in the official build), they must be provided otherwise SDS will not work. When we built netcdf4.dll, we statically linked those libraries inside the netcdf4.dll.  So official library should work, but I don't know which additional libraries it may require to be presented.

C# code doesn't need netcdf.h; instead, explicit "DllImport" attributes define which exported methods from an unmanaged library we import.

 

 

Jun 14, 2011 at 8:47 AM

Thanks.

I am able to use the dll that I built.  

The exception that I met is that using reference as content in .Net 4.0 throws exception PInvoker has unbalanced the stack.

Below is that code that I use with NetCDF 4.1.1. For some reason, it throws exception at the last line of code ' NetCDFInterop.nc_close'...

namespace NetCDFCrashingCode
{
    class Program
    {
        static void Main(string[] args)
        {
            int i;
            string path = @"C:\data_11.nc";
            //NetCDFInterop.nc_create(MarshalString(path), (int)CreateMode.NC_NETCDF4, out i);
            NetCDFInterop.nc_create(path, CreateMode.NC_NETCDF4, out i);
            NetCDFInterop.nc_redef(i);
            NetCDFInterop.nc_put_att_string(i, -1, MarshalString("history"), new IntPtr(1), MarshalStringArray(new String[] { "his" }));
            NetCDFInterop.nc_enddef(i);
            NetCDFInterop.nc_sync(i);
            NetCDFInterop.nc_close(i);
            NetCDFInterop.nc_open(@"C:\data_11.nc", CreateMode.NC_WRITE, out i);
            NetCDFInterop.nc_close(i);
        }

        public static IntPtr MarshalString(string str)
        {
            byte[] array = Encoding.UTF8.GetBytes(str);
            int size = Marshal.SizeOf(typeof(byte)) * (array.Length + 1);
            IntPtr ptr = Marshal.AllocHGlobal(size);
            Marshal.Copy(array, 0, ptr, array.Length);
            Marshal.WriteByte(ptr, array.Length, 0);
            return ptr;
        }

        public static IntPtr MarshalStringArray(string[] strArr)
        {
            int n = strArr.Length;
            int sz = Marshal.SizeOf(typeof(byte*));
            IntPtr ptrA = Marshal.AllocHGlobal(sz * n);
            for (int i = 0; i < n; i++)
            {
                Marshal.WriteIntPtr(ptrA, sz * i, MarshalString(strArr[i]));
            }
            return ptrA;
        }
    }

    public enum CreateMode : int
    {
        NC_NOWRITE = 0,
        /// <summary>read &amp; write</summary>
        NC_WRITE = 0x0001,
        NC_CLOBBER = 0,
        /// <summary>Don't destroy existing file on create</summary>
        NC_NOCLOBBER = 0x0004,
        /// <summary>argument to ncsetfill to clear NC_NOFILL</summary>
        NC_FILL = 0,
        /// <summary>Don't fill data section an records</summary>
        NC_NOFILL = 0x0100,
        /// <summary>Use locking if available</summary>
        NC_LOCK = 0x0400,
        /// <summary>Share updates, limit cacheing</summary>
        NC_SHARE = 0x0800,
        NC_64BIT_OFFSET = 0x0200,
        /// <summary>Enforce strict netcdf-3 rules</summary>
        NC_CLASSIC = 0x0100,
        /// <summary>causes netCDF to create a HDF5/NetCDF-4 file</summary>
        NC_NETCDF4 = 0x1000
    }

    public static class NetCDFInterop
    {
        [DllImport("netcdf4.dll")]
        public static extern int nc_create(string path, CreateMode cmode, out int ncidp);
        //public static extern int nc_create(IntPtr path, int cmode, out int ncidp);

        [DllImport("netcdf4.dll")]
        public static extern int nc_open(string path, CreateMode omode, out int ncidp);
        [DllImport("netcdf4.dll")]
        public static extern int nc_close(int ncidp);
        [DllImport("netcdf4.dll")]
        public static extern int nc_sync(int ncid);
        [DllImport("netcdf4.dll")]
        public static extern int nc_enddef(int ncid);
        [DllImport("netcdf4.dll")]
        public static extern int nc_redef(int ncid);

        //[DllImport("netcdf4.dll")]
        //public static extern int nc_put_att_string(int ncid, int varid,
        //    [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]
        //    string name,
        //    IntPtr len,
        //    [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]
        //    String[] op);
        [DllImport("netcdf4.dll")]
        public static extern int nc_put_att_string(int ncid, int varid,
            IntPtr name,
            IntPtr len,
            IntPtr op);
    }
}

Do you have any clue? I think this is the issue of NetCDF, thus I also posted it to NetCDF community..