none
marshalling strings RRS feed

  • Question

  • I am working with a 3rd party C++ unmanaged DLL. It has the following export:

            HRESULT GetPhocusVersion( HANDLE hClient, LPWSTR szVersion, INT maxChar );

    And I use the following

            [DllImport("PhocusApi64.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
            public static extern Int32 GetPhocusVersion(IntPtr hClient, String PhocusVersion, Int32 macChar);

    In my C# code, I use the following:

                Int32 MaxChar = 260;  //max length of the returned String
                String PhocusVersion = "";
                for (int i = 0; i < MaxChar; i++) PhocusVersion += " ";  //must fill the string or else get an error
                Result = PhocusDLLImports.GetPhocusVersion(hClient, PhocusVersion, MaxChar);

    This works fine. But is there a way to marshal the string w/o having to initialize it with a ling string?

       Jim

    Wednesday, July 25, 2018 3:49 PM

Answers

  • It depends upon how the unmanaged code works. If the unmanaged code will set the string to a value but you have to specify the size of that buffer then using a preallocated string would work. The preference is to use StringBuilder though. The marshaller will see this type and handle the conversion.

    [DllImport(…, EntryPoint="GetPhocusVersion")]
    private static extern int GetPhocusVersionW ( IntPtr hClient, StringBuilder phocusVersion, int maxChar );
    
    
    public static extern string GetPhocusVersion ( IntPtr hClient )
    {
       var builder = new StringBuilder(256);
       
       //Ignoring error handling here...
       GetPhocusVersionW(hClient, builder, builder.Capacity + 1);
    
       return builder.ToString();
    }
    Documentation has the full discussion here.


    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, July 25, 2018 5:52 PM
    Moderator

All replies

  • Many Win32 APIs work with StringBuilder, but not sure for your case.

    Like :

    StringBuilder sbString = new StringBuilder(260);
    int nSize = sbString.Capacity;
    function(sbString, ref nSize, ...);
    string sRetString = sbString.ToString();

    Wednesday, July 25, 2018 4:10 PM
  • Stringbuilder is a tool I've never adopted.

    "Pre-setting the String" seems about as practical. I thought there was a way to use the [Marshalas ...] syntax to prevent having to have the returned string already set to a  suitable size ..

       Jim

    Wednesday, July 25, 2018 5:12 PM
  • It depends upon how the unmanaged code works. If the unmanaged code will set the string to a value but you have to specify the size of that buffer then using a preallocated string would work. The preference is to use StringBuilder though. The marshaller will see this type and handle the conversion.

    [DllImport(…, EntryPoint="GetPhocusVersion")]
    private static extern int GetPhocusVersionW ( IntPtr hClient, StringBuilder phocusVersion, int maxChar );
    
    
    public static extern string GetPhocusVersion ( IntPtr hClient )
    {
       var builder = new StringBuilder(256);
       
       //Ignoring error handling here...
       GetPhocusVersionW(hClient, builder, builder.Capacity + 1);
    
       return builder.ToString();
    }
    Documentation has the full discussion here.


    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, July 25, 2018 5:52 PM
    Moderator