Solved

Convert Unsafe c to C# wrapper to safe code

Posted on 2007-11-26
12
374 Views
Last Modified: 2010-04-21
The parent question this code came from was:http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/Q_22976921.html
This question has the C source code and the header:  I just want to get this code to SAFE C# code.
[StructLayout(LayoutKind.Sequential)]
private struct APCDeviceDescription {
    public IntPtr next;
    public IntPtr name;
    public IntPtr description;
}
 
public class APCDevice {
    public string name;
    public string description;
}
 
[DllImport("airpcap.dll")]
private extern static unsafe int AirpcapGetDeviceList(APCDeviceDescription** ppDevices, char* pBuf);
 
[DllImport("airpcap.dll")]
private extern static unsafe int AirpcapFreeDeviceList(APCDeviceDescription* pDevices);
 
public static unsafe int AirpcapGetDeviceListWrap(out APCDevice[] outDevices, ref string outErrors) {
    List<APCDevice> devicesToRet = new List<APCDevice>();
    APCDeviceDescription* pDevices = (APCDeviceDescription*)0;
    APCDeviceDescription** ppDevices = &pDevices;
    char*pErrorBuffer = stackalloc char[513];
    int result = 0;
    try {
        result = AirpcapGetDeviceList(ppDevices, pErrorBuffer);
    } finally {
        if (result != 0) {
            APCDeviceDescription* pDevice = pDevices;
            while (pDevice != (APCDeviceDescription*)0) {
                APCDevice newDev = new APCDevice();
                newDev.name = Marshal.PtrToStringAnsi(pDevice->name);
                newDev.description = Marshal.PtrToStringAnsi(pDevice->description);
                devicesToRet.Add(newDev);
                pDevice = (APCDeviceDescription*)pDevice->next;
            }
            AirpcapFreeDeviceList(pDevices);
            //
            outDevices = devicesToRet.ToArray();
            outErrors = null;
        } else {
            List<char> listChars = new List<char>();
            char charFromBuf = pErrorBuffer[0];
            while (charFromBuf != 0) {
                listChars.Add(charFromBuf);
            }
            char[] errorsCharArray = listChars.ToArray();
            //
            outErrors = new String(errorsCharArray);
            outDevices = null;
        }
    }
    return ( result );
}

Open in new window

0
Comment
Question by:mileyja
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 5
12 Comments
 
LVL 3

Expert Comment

by:wizrr
ID: 20354696
Hi again. I think now i know how to do that. Pointer is 32bit value, we can declare structure with same size and use Marshal.PtrToStructure/Marshal.StructureToPtr methods to do that.

I'm not sure. You must test.
[StructLayout(LayoutKind.Sequential)]
private struct APCDeviceDescription {
    public IntPtr next;
    public IntPtr name;
    public IntPtr description;
}
 
[StructLayout(LayoutKind.Sequential)]
private struct APCDeviceDescriptionPointer {
    public IntPtr pointer;
}
 
public class APCDevice {
    public string name;
    public string description;
}
 
[DllImport("airpcap.dll")]
private extern static int AirpcapGetDeviceList(IntPtr ppDevices, StringBuilder pBuf);
 
[DllImport("airpcap.dll")]
private extern static int AirpcapFreeDeviceList(APCDeviceDescriptionPointer pDevices);
 
public static int AirpcapGetDeviceListWrap(out APCDevice[] outDevices, ref string outErrors) {
    List<APCDevice> devicesToRet = new List<APCDevice>();
    APCDeviceDescriptionPointer pDevices;
    pDevices.pointer = IntPtr.Zero;
    //
    // now let's do that:
    // APCDeviceDescription** ppDevices = &pDevices;
    IntPtr ppDevices = Marshal.AllocHGlobal(Marshal.SizeOf(APCDeviceDescriptionPointer));
    Marshal.StructureToPtr(pDevices, ppDevices, false);
    
    StringBuilder builder = new StringBuilder(513);
    int result = 0;
    try {
        result = AirpcapGetDeviceList(ppDevices, builder );
    } finally {
 
        if (result != 0) {
            // get pointer from pointer-to-pointer
            APCDeviceDescriptionPointer pointer2 = Marshal.PtrToStructure(ppDevices, typeof(APCDeviceDescriptionPointer));
            // get structure from pointer
            APCDeviceDescription pointer3 = Marshal.PtrToStructure(pointer2.pointer, typeof(APCDeviceDescription));
            while (pointer3 != IntPtr.Zero) {
                APCDevice newDev = new APCDevice();
                newDev.name = Marshal.PtrToStringAnsi(pDevice->name);
                newDev.description = Marshal.PtrToStringAnsi(pDevice->description);
                devicesToRet.Add(newDev);
                // get next structure
                pointer3 = Marshal.PtrToStructure(pointer3.next, typeof(APCDeviceDescription));
            }
            AirpcapFreeDeviceList(pointer2);
            //
            outDevices = devicesToRet.ToArray();
            outErrors = null;
        } else {
            //
            outErrors = new String(buffer.ToString());
            outDevices = null;
        }
        if ( ppDevices != IntPtr.Zero ) {
            Marshal.FreeHGlobal(ppDevices);
            ppDevices = IntPtr.Zero;
        }
    }
    return ( result );
}

Open in new window

0
 
LVL 3

Expert Comment

by:wizrr
ID: 20354710
Damn. Sorry.
There
-------
APCDeviceDescription pointer3 = Marshal.PtrToStructure(pointer2.pointer, typeof(APCDeviceDescription));
            while (pointer3 != IntPtr.Zero) {
                APCDevice newDev = new APCDevice();
                newDev.name = Marshal.PtrToStringAnsi(pDevice->name);
                newDev.description = Marshal.PtrToStringAnsi(pDevice->description);
                devicesToRet.Add(newDev);
                // get next structure
                pointer3 = Marshal.PtrToStructure(pointer3.next, typeof(APCDeviceDescription));
            }

--------
Should be
--------

 if (pointer2.pointer != IntPtr.Zero) {
    APCDeviceDescription pointer3 = Marshal.PtrToStructure(pointer2.pointer, typeof(APCDeviceDescription));
            while (true) {
               
                APCDevice newDev = new APCDevice();
                newDev.name = Marshal.PtrToStringAnsi(pDevice->name);
                newDev.description = Marshal.PtrToStringAnsi(pDevice->description);
                devicesToRet.Add(newDev);
                // get next structure
                if ( pointer3.next == IntPtr.Zero )
                     break;
                pointer3 = Marshal.PtrToStructure(pointer3.next, typeof(APCDeviceDescription));
            }

0
 

Author Comment

by:mileyja
ID: 20354726
 IntPtr ppDevices = Marshal.AllocHGlobal(Marshal.SizeOf(APCDeviceDescriptionPointer)); gives
Error      5      'GetDeviceList2.AirpcapInterface.APCDeviceDescriptionPointer' is a 'type' but is used like a 'variable'      
 im guess int this is suppposed to be pDevices

     APCDeviceDescriptionPointer pointer2 = Marshal.PtrToStructure(ppDevices, typeof(APCDeviceDescriptionPointer));
gives:
Error      6      Cannot implicitly convert type 'object' to 'GetDeviceList2.AirpcapInterface.APCDeviceDescriptionPointer'.

while (pointer3 != IntPtr.Zero)
Gives:
Error      8      Operator '!=' cannot be applied to operands of type 'GetDeviceList2.AirpcapInterface.APCDeviceDescription' and 'System.IntPtr'      

    outErrors = new String(buffer.ToString());
I dont think "buffer" is declared, thats basically what its telling me,

im running out of juice and im in class Ill probably test this more after class and get back to you if you can try to reconcile those items.

Thanks
0
Webinar: Aligning, Automating, Winning

Join Dan Russo, Senior Manager of Operations Intelligence, for an in-depth discussion on how Dealertrack, leading provider of integrated digital solutions for the automotive industry, transformed their DevOps processes to increase collaboration and move with greater velocity.

 

Author Comment

by:mileyja
ID: 20354734
thanks ill dig into her more after class at 10ish cst
0
 
LVL 3

Expert Comment

by:wizrr
ID: 20354746
See previous post. Also try
Marshal.SizeOf(typeof(APCDeviceDescriptionPointer))
instead of
Marshal.SizeOf(APCDeviceDescriptionPointer)
//
Also
APCDeviceDescriptionPointer pointer2 = (APCDeviceDescriptionPointer)Marshal.PtrToStructure...
instead of
APCDeviceDescriptionPointer pointer2 = Marshal.PtrToStructure...
//
And last. Ofcourse not buffer. I mean 'builder'.
0
 

Author Comment

by:mileyja
ID: 20367123
Ive got my brackets all messed up. somehow

below is what I did
       public static int AirpcapGetDeviceListWrap(out APCDevice[] outDevices, ref string outErrors)
        {
            List<APCDevice> devicesToRet = new List<APCDevice>();
            APCDeviceDescriptionPointer pDevices;
            pDevices.pointer = IntPtr.Zero;
            //
            // now let's do that:
            // APCDeviceDescription** ppDevices = &pDevices;
            IntPtr ppDevices = Marshal.AllocHGlobal(Marshal.SizeOf(APCDeviceDescriptionPointer));
            Marshal.StructureToPtr(pDevices, ppDevices, false);
 
            StringBuilder builder = new StringBuilder(513);
            int result = 0;
            try
            {
                result = AirpcapGetDeviceList(ppDevices, builder);
            }
            finally
            {
 
                if (result != 0)
                {
                    // get pointer from pointer-to-pointer
                    if (pointer2.pointer != IntPtr.Zero) {
                      APCDeviceDescription pointer3 = Marshal.PtrToStructure(pointer2.pointer, typeof(APCDeviceDescription));
            while (true) {
               
                APCDevice newDev = new APCDevice();
                newDev.name = Marshal.PtrToStringAnsi(pDevice->name);
                newDev.description = Marshal.PtrToStringAnsi(pDevice->description);
                devicesToRet.Add(newDev);
                // get next structure
                if ( pointer3.next == IntPtr.Zero ) {
                     break;
                pointer3 = Marshal.PtrToStructure(pointer3.next, typeof(APCDeviceDescription));
            }}
 
                else
                {
                    //
                    outErrors = new String(buffer.ToString());
                    outDevices = null;
                }
                if (ppDevices != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(ppDevices);
                    ppDevices = IntPtr.Zero;
                }}
            
            return (result);
        } }
 
        // /////////ENDING GET DEVICE LIST STUFF///////////////////////////////////////////////
 
    }}

Open in new window

0
 
LVL 3

Expert Comment

by:wizrr
ID: 20367169
Marshal.SizeOf(typeof(APCDeviceDescriptionPointer))

instead of

Marshal.SizeOf(APCDeviceDescriptionPointer)
public static int AirpcapGetDeviceListWrap(out APCDevice[] outDevices, ref string outErrors)
        {
            List<APCDevice> devicesToRet = new List<APCDevice>();
            APCDeviceDescriptionPointer pDevices;
            pDevices.pointer = IntPtr.Zero;
            //
            // now let's do that:
            // APCDeviceDescription** ppDevices = &pDevices;
            IntPtr ppDevices = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(APCDeviceDescriptionPointer)));
            Marshal.StructureToPtr(pDevices, ppDevices, false);
 
            StringBuilder builder = new StringBuilder(513);
            int result = 0;
            try
            {
                result = AirpcapGetDeviceList(ppDevices, builder);
            }
            finally
            {
 
                if (result != 0)
                {
                    // get pointer from pointer-to-pointer
                    if (pointer2.pointer != IntPtr.Zero) {
                      APCDeviceDescription pointer3 = (APCDeviceDescription)Marshal.PtrToStructure(pointer2.pointer, typeof(APCDeviceDescription));
            while (true) {
               
                APCDevice newDev = new APCDevice();
                newDev.name = Marshal.PtrToStringAnsi(pDevice->name);
                newDev.description = Marshal.PtrToStringAnsi(pDevice->description);
                devicesToRet.Add(newDev);
                // get next structure
                if ( pointer3.next == IntPtr.Zero ) {
                     break;
                pointer3 = (APCDeviceDescription)Marshal.PtrToStructure(pointer3.next, typeof(APCDeviceDescription));
            }}
 
                else
                {
                    //
                    outErrors = new String(builder.ToString());
                    outDevices = null;
                }
                if (ppDevices != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(ppDevices);
                    ppDevices = IntPtr.Zero;
                }}
            
            return (result);
        } }
 
        // /////////ENDING GET DEVICE LIST STUFF///////////////////////////////////////////////
 
    }}

Open in new window

0
 

Author Comment

by:mileyja
ID: 20367203
also you dont ever actually dim that pointer 2 i read the above post but it was kind of hard to understand.
0
 

Author Comment

by:mileyja
ID: 20367206
you did the elipsis (...) thing again and I don't know where to stick that statement either.
0
 
LVL 3

Accepted Solution

by:
wizrr earned 500 total points
ID: 20367266
Here. That code compiled normally and should be without errors:
[StructLayout(LayoutKind.Sequential)]
private struct APCDeviceDescription {
	public IntPtr next;
	public IntPtr name;
	public IntPtr description;
}
 
[StructLayout(LayoutKind.Sequential)]
private struct APCDeviceDescriptionPointer {
	public IntPtr pointer;
}
 
public class APCDevice {
	public string name;
	public string description;
}
 
[DllImport("airpcap.dll")]
private extern static int AirpcapGetDeviceList(IntPtr ppDevices, StringBuilder pBuf);
 
[DllImport("airpcap.dll")]
private extern static int AirpcapFreeDeviceList(APCDeviceDescriptionPointer pDevices);
 
 
public static int AirpcapGetDeviceListWrap(out APCDevice[] outDevices, ref string outErrors)
{
	List<APCDevice> devicesToRet = new List<APCDevice>();
	APCDeviceDescriptionPointer pDevices;
	pDevices.pointer = IntPtr.Zero;
	//
	outDevices = null;
	outErrors = null;
//
	// now let's do that:
	// APCDeviceDescription** ppDevices = &pDevices;
	IntPtr ppDevices = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(APCDeviceDescriptionPointer)));
	Marshal.StructureToPtr(pDevices, ppDevices, false);
 
	StringBuilder builder = new StringBuilder(513);
	int result = 0;
	try
	{
		result = AirpcapGetDeviceList(ppDevices, builder);
	}
	finally
	{
		if (result != 0)
		{
			// get pointer from pointer-to-pointer
			APCDeviceDescriptionPointer pointer2 = (APCDeviceDescriptionPointer)Marshal.PtrToStructure(ppDevices, typeof(APCDeviceDescriptionPointer));
 
			if (pointer2.pointer != IntPtr.Zero) {
				APCDeviceDescription pDevice = (APCDeviceDescription)Marshal.PtrToStructure(pointer2.pointer, typeof(APCDeviceDescription));
				while (true) {
 
					APCDevice newDev = new APCDevice();
					newDev.name = Marshal.PtrToStringAnsi(pDevice.name);
					newDev.description = Marshal.PtrToStringAnsi(pDevice.description);
					devicesToRet.Add(newDev);
					// get next structure
					if ( pDevice.next == IntPtr.Zero ) {
						break;
					}
					pDevice = (APCDeviceDescription)Marshal.PtrToStructure(pDevice.next, typeof(APCDeviceDescription));
				}
				//
				outDevices = devicesToRet.ToArray();
				outErrors = null;
 
			}
			else
			{
				outErrors = builder.ToString();
				outDevices = null;
			}
		}
		if (ppDevices != IntPtr.Zero)
		{
			Marshal.FreeHGlobal(ppDevices);
			ppDevices = IntPtr.Zero;
		}
	}
	// /////////ENDING GET DEVICE LIST STUFF///////////////////////////////////////////////
	return (result);
}

Open in new window

0
 

Author Comment

by:mileyja
ID: 20367480
good call, works beautifully
0
 

Author Closing Comment

by:mileyja
ID: 31411108
I am starting to figure out how this works on my own, I feel silly asking all these questions, I guess that happens when you are working with unmanaged to managed code and you have never used either C or C# before.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Secondary drive is failing... D Volume 11 49
Problem to Office 1 40
Data organization issue 7 36
C# Windows Form Navigation - Total Beginner 9 40
More often than not, we developers are confronted with a need: a need to make some kind of magic happen via code. Whether it is for a client, for the boss, or for our own personal projects, the need must be satisfied. Most of the time, the Framework…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
The goal of this video is to provide viewers with basic examples to understand and use structures in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use for-loops in the C programming language.

756 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question