Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1788
  • Last Modified:

Importing a C-style .dll AND marshalling confusing data types.

I am using the .NET Interop services to import a .dll written in C.  One of the functions in the .dll has some very confusing data types.  I'm new to marshalling data types - anyone want to help?

//// The original C-style function declaration looks something like this:
__int32 FunctionName( void * A, const char * B, unsigned char * C, unsigned __int32 D, unsigned char ** E, unsinged __int32 * F, unsigned char ** G, unsigned __int32 * G);

//// My C# code will look something like this:
using System;
using System.Runtime.InteropServices;

namespace SomeNamespace
{
   public class SomeClass
   {
        [ DllImport( "SomeLibrary.dll" )]
        public static extern int FunctionName( ..... WHAT SHOULD I DO NEXT ????? )
   }
}

//////////
So, my question is: what C# treatment do I give all those ugly C-style data types???

Thanks!!!
0
TheGooch
Asked:
TheGooch
  • 2
1 Solution
 
AlexFMCommented:
All pointers (including **) should be passed as IntPtr.
Rwad about Marshal class. You need its functions to prepare input parameters to this function and to read output parameters.
For example, if A parameter expects pointer to some data, allocate memory block in C# using Marshal.AllocHGlobal Method. It returns IntPtr. Fill this block using unsafe programming and pass IntPtr to FunctionName.
If B points to ansi string, use Marshal.StringToHGlobalAnsi Method to allocate this string on non-managed heap and pass result IntPtr to the function.
Double pointer (**) may be passed as IntPtr ref or out parameter.
0
 
AlexFMCommented:
After reading your question I decided to make small C# PInvoke exersize. I hope it can help you. Consider the following C Dll:

// Function gets void* pointer and increments
// 3 starting bytes in it
SERVERDLL_API void Function1(void* p)
{
    char* pc = (char*) p;

    (*pc++)++;
    (*pc++)++;
    (*pc++)++;
}

// Function gets const pointer to string
SERVERDLL_API void Function2(const char* p)
{
    MessageBox(NULL, p, NULL, MB_OK);
}


// Function gets pointer to integer
SERVERDLL_API void Function3(int* p)
{
    *p = 10;
}

// Function gets char** and allocates ansi string
SERVERDLL_API void Function4(char** p)
{
    *p = new char[20];
    strcpy(*p, "string from C");
}

// Function releases char* string
SERVERDLL_API void Release(char* p)
{
    delete[] p;
}

This is C# console application which calls all these functions:


namespace PInvokeClient
{
    class Class1
    {

        #region void* parameter (Test 1)

        [DllImport ("ServerDll.dll")]
        public static extern void Function1(IntPtr p);

        static void Test1()
        {
            // allocate memory on unmanaged heap
            IntPtr ptr = Marshal.AllocHGlobal(3);

            // Fill is with 3 bytes
            unsafe
            {
                byte* pByte = (byte*)ptr;

                *pByte = 50;
                *(pByte+1) = 51;
                *(pByte+2) = 52;
            }

            Function1(ptr);   // increment each bytes

            // read result (output is 51, 52, 53)
            unsafe
            {
                byte* pByte = (byte*)ptr;

                Console.WriteLine( *pByte );
                Console.WriteLine( *(pByte+1) );
                Console.WriteLine( *(pByte+2) );
            }

            // free memory
            Marshal.FreeHGlobal(ptr);
        }
        #endregion


        #region const char* parameter (Test 2)

        [DllImport ("ServerDll.dll")]
        public static extern void Function2(IntPtr p);

        static void Test2()
        {
            String s = @"String from C#";

            // allocate string on unmanaged heap
            IntPtr ptr = Marshal.StringToHGlobalAnsi(s);

            Function2(ptr);


            // free memory
            Marshal.FreeCoTaskMem(ptr);
        }
        #endregion


        #region int* parameter (Test 3)

        [DllImport ("ServerDll.dll")]
        public static extern void Function3(IntPtr p);

        static void Test3()
        {
            // allocate memory on unmanaged heap
            IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(int)));

            Function3(ptr);

            // read result
            unsafe
            {
                int* pInt = (int*)ptr;

                Console.WriteLine( *pInt );
            }

            // free memory
            Marshal.FreeHGlobal(ptr);
        }
        #endregion

        #region char** parameter (Test 4)

        [DllImport ("ServerDll.dll")]
        public static extern void Function4(out IntPtr p);
        [DllImport ("ServerDll.dll")]
        public static extern void Release(IntPtr p);

        static void Test4()
        {
            IntPtr ptr;

            Function4(out ptr);

            string s = Marshal.PtrToStringAnsi(ptr);

            Console.WriteLine(s);

            Release(ptr);

        }
        #endregion


        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            Test1();
            Test2();
            Test3();
            Test4();
        }
    }
}

As you see, handling of C function parameters depends on their type and function algorithm. Marshal class and unsafe programming make C# program flexible enough to call various C functions.

Read also this article:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp09192002.asp
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now