Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a C DLL Function With char* Parameters With P/Invoke

Tags:

c#

dll

pinvoke

I've read other similar questions on this but they don't solve this particular problem. I have an old C-library with a touppercase function (as an example). This takes a char* and returns a char*. However, the pointer returned is a pointer to the same string (don't ask me I didn't write it).

The function looks like this:

__declspec(dllexport)
char * __cdecl touppercase(char *ps_source)
{
    char *ps_buffer = NULL;

    assert (ps_source != NULL);

    ps_buffer = ps_source;
    while (*ps_buffer != '\0')
    {
        *ps_buffer = toupper(*ps_buffer);
        ps_buffer++;
    }
*ps_buffer = '\0';
    return (ps_source);
}

The C# code to declare this looks like:

    [DllImport("mydll.dll", EntryPoint = "touppercase",
               CharSet = CharSet.Ansi, ExactSpelling = true,
               CallingConvention = CallingConvention.Cdecl)]
    private static extern System.IntPtr touppercase(string postData);

The call to this in my app looks like

     string sTest2 = Marshal.PtrToStringAnsi(to_uppercase(sTest));

However sTest2 just ends up being a random string.

I added a test function to the same dll with the same parameters but this allocates memory locally and copies the string. This works fine. Why does the original version now work?

Note: Updating the dll libraries themselves isn't an option.

like image 605
Jonnster Avatar asked May 27 '11 14:05

Jonnster


1 Answers

The function is modifying the reference so you should use a stringbuilder:

[DllImport("dll.dll", EntryPoint="touppercase",
CharSet = CharSet.Ansi, ExactSpelling = true,
CallingConvention = CallingConvention.Cdecl)]
private static extern System.IntPtr touppercase(StringBuilder postData);

Call it something like this:

    StringBuilder sTest = new StringBuilder("abs");
    touppercase(sTest);
    string result = sTest.ToString();

For the explanation of the return pointer -> Ben Voigt

like image 54
Marino Šimić Avatar answered Oct 23 '22 17:10

Marino Šimić