C# application crashes after I get a string from a C++ dll

Traitée C# application crashes after I get a string from a C++ dll

  • vendredi 16 mars 2012 02:59
     
     

    Hi there,

    I try to get a string from my C++ dll in C# application.

    My code snippet is below:

    ===== C++ dll =====

    __declspec(dllexport) void GetSzString(char** pszString, size_t nLength)
    {
        if(*pszString == NULL) {
            return;
        }

        strcpy_s(*pszString, nLength, "Hello,World");
    }

    ===== C# App =====

    class Program

        [DllImport("CppDll.dll")]
        public static extern void GetSzString(ref string rStr, int length);

        static void Main(string[] args)
        {
            string myStr = "";
            GetSzString(ref myStr, 128);
            Console.WriteLine("The string is {0}", myStr);

            Console.Read();
        }
    }

    I get the string "Hello,World" successfully. it shows on my console window.

    However, my C# application crashes when it is closing.

    What's wrong with my code.

    What's the correct way to get a string from a C++ dll.

Toutes les réponses

  • vendredi 16 mars 2012 04:31
     
     

    I think .NET is trying to free memory that it doesn't own, and already freed when doing execution environment tear down.

    Try change the import signiture to use StringBuilder instead of ref string, the C# compiler has hardcoded to make necessary changes to the call when it sees StringBuilder as parameter.



  • vendredi 16 mars 2012 05:02
     
      A du code

    You can try using the attribute MarshalAs

        [return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)]

    http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshalasattribute.aspx

    If allowed please upload the dll so we can try it out here:


    Resolving n Evolving in C# (http://jeanpaulva.com)


  • vendredi 16 mars 2012 06:14
     
     Traitée

    Hi Cheong,

    I modify my C# code

    ===== C# application =====

    [DllImport("CppExDll.dll")]
    public static extern void GetSzString(StringBuilder sb, int length);

    static void Main(string[] args)
    {
        StringBuilder mySB = new StringBuilder(128);
        GetSzString(mySB, 128);
        Console.WriteLine("The string is {0}", mySB);

        Console.Read();
    }

    It gets a empty string, the "Hello,World" doesn't show on my console window.

    But, there is no crash when app is closing.

    Then, I modify my code again (use ref StringBuilder instead)

    ===== C# application =====

    [DllImport("CppExDll.dll")]
    public static extern void GetSzString(ref StringBuilder sb, int length);

    static void Main(string[] args)
    {
        StringBuilder mySB = new StringBuilder(128);
        GetSzString(ref mySB, 128);
        Console.WriteLine("The string is {0}", mySB);

        Console.Read();
    }

    It works. I get the "Hello,World" successfully and there is no crash when app is closing.

    I think that it might be a correct way to get a string from C++ dll.

    Thanks

  • vendredi 16 mars 2012 06:24
     
     

    Hi Jean,

    I use the attribute MarshalAs, and I get a strange string.

    (Because the UnmanagedType.LPWStr is used?)

    ===== C# application =====

    [DllImport("CppExDll.dll")]
    public static extern void GetSzString(
        [MarshalAsAttribute(UnmanagedType.LPWStr)]
        ref string rStr, 
        int length);

    static void Main(string[] args)
    {
        StringBuilder mySB = new StringBuilder(128);
        GetSzString(ref mySB, 128);
        Console.WriteLine("The string is {0}", mySB);

        Console.Read();
    }

    And my app still crash.

    By the way, I don't know how to upload my dll.

    Thanks.

  • vendredi 16 mars 2012 06:32
     
     

    Hello Lee,

    You can upload the file to rapidshare/skydrive/web servers and provide the link.

    But as of now you got the problem solved, I think it is not needed.


    Resolving n Evolving in C# (http://jeanpaulva.com)

  • vendredi 16 mars 2012 08:46
     
     
    You pass ref StringBuilder since the function expects a char**. Passing StringBuilder without the ref keyword would pass a char* only.
  • vendredi 16 mars 2012 09:07
     
     
    True. You would need to set the CharSet of the DllImport attribute. It doesn't matter anyway, since the OP is using char**.
  • vendredi 16 mars 2012 10:14
     
     
    You're right. I've overlooked the char** here. (Not seeing your reply before decided to delete the post)