使用带有P/Invoke的char*参数调用C DLL函数

Jon*_*ter 5 c# dll pinvoke

我已经阅读了其他类似的问题,但他们没有解决这个特殊的问题.我有一个带有touppercase功能的旧C库(作为示例).这需要一个char*并返回一个char*.但是,返回的指针是指向同一个字符串的指针(不要问我没写它).

该函数如下所示:

__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);
}
Run Code Online (Sandbox Code Playgroud)

声明它的C#代码如下所示:

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

我的应用程序中对此的调用看起来像

     string sTest2 = Marshal.PtrToStringAnsi(to_uppercase(sTest));
Run Code Online (Sandbox Code Playgroud)

然而,sTest2最终只是一个随机字符串.

我使用相同的参数向同一个dll添加了一个测试函数,但这会在本地分配内存并复制字符串.这很好用.为什么原始版本现在可以使用?

注意:不能更新dll库本身.

Mar*_*mić 10

该函数正在修改引用,因此您应该使用stringbuilder:

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

称之为:

    StringBuilder sTest = new StringBuilder("abs");
    touppercase(sTest);
    string result = sTest.ToString();
Run Code Online (Sandbox Code Playgroud)

有关返回指针的解释 - > Ben Voigt