DllImport and char Marshaling

13,257

public static extern IntPtr Ololo([In] char[] arg, ref Int32 n3);

IntPtr is the wrong return type, as essentially you want to return the string, not a pointer to the string. In C you can use a pointer to your string by using char*, the equivalent in .NET would be to use use this: [MarshalAs(UnmanagedType.LPStr)]string. This should marshall the char* to a string correctly.

IntPtr represents a pointer type, which to get your actual string is useless.

Also looks like you should be taking a StringBuilder into your Marshalled function, and not a char[]. Then at least you should be getting the correct string to your C function.

Share:
13,257
Treno1
Author by

Treno1

Updated on June 04, 2022

Comments

  • Treno1
    Treno1 almost 2 years

    I'm newbie at C# and Marshaling. I need to use my C func in C#, but i have an incorrect return value from C func (or I don't know how to convert it to correct answer).

    C source:

    #include "main.h"
    
    char *Ololo(char *arg, int &n3)
    {
        char *szRet;
        szRet=(char*)malloc(strlen(arg)+1);
        strcpy(szRet,arg);
        n3 = strlen(szRet);
        return szRet;
    }
    

    C header:

    extern "C" __declspec(dllexport) char *Ololo(char *arg, int &n3);
    

    C# source:

    class Program
    {
        [DllImport(@"F:\Projects\service\dll\testDLL2.DLL", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
        public static extern IntPtr Ololo([In] char[] arg, ref Int32 n3);
    
        static void Main(string[] args)
        {
            string n1 = "ololo";
            char[] chars = new char[n1.Length];
            chars = n1.ToCharArray();
            Int32 n3 = 0;
            IntPtr result;
            result = Ololo(chars, ref n3);
            string n4 = Marshal.PtrToStringUni(result,n3);
            Console.WriteLine(n4);
        }
    }
    

    I've got return something like "o?? ?"

    Sorry for bad English

    ----------------------Solved-----------------------

    class Program
        {
            [DllImport(@"F:\Projects\service\dll\testDLL2.DLL", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
            public static extern IntPtr Ololo([MarshalAs(UnmanagedType.LPStr)]string arg, ref Int32 n3);
    
            static void Main(string[] args)
            {
                string n1 = "ololo";
                Int32 n3 = 0;
                int n2 = n1.Length;
                IntPtr result;
                result = Ololo(n1, ref n3);
                string n4 = Marshal.PtrToStringAnsi(result, n3);
                Console.WriteLine(n4);
            }
        }
    

    That works fine. In n3 i ve got 5 and in n4 ololo! Thank s for quick answers!

  • Treno1
    Treno1 over 11 years
    I think IntPtr is correct because n3 returns me 1 and int IntPtr Ive got first letter (o). But why I have n3` = 1? I think it needs to be 5. Because of that I think [In] char[] arg` is incorrect. But what is correct?
  • Tony The Lion
    Tony The Lion over 11 years
    @Treno1 your function in .NET will never give you the entire string back if you return IntPtr.
  • Treno1
    Treno1 over 11 years
    VS 2010 think that public static extern [MarshalAs(UnmanagedType.LPStr)]string Ololo is incorrect because of [MarshalAs(UnmanagedType.LPStr)] cannot be in declaration of class , structure or interface.
  • Puppy
    Puppy over 11 years
    It isn't. You must have failed to copy the DLLImport attribute over, or placed the declaration in the wrong place.
  • Treno1
    Treno1 over 11 years
    System.AccessViolationException if I try to public static extern StringBuilder Ololo(string arg, ref Int32 n3); and StringBuilder n5 = Ololo(n1, ref n3);