我已经阅读了其他类似的问题,但他们没有解决这个问题。我有一个带touppercase函数的旧C库(作为例子)。这需要一个char *并返回一个char *。但是,返回的指针是一个指向同一个字符串的指针(不要问我,我没有写它)。使用char *参数调用C DLL函数使用P/Invoke
功能如下:
__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);
}
的C#代码来声明这个样子:
[DllImport("mydll.dll", EntryPoint = "touppercase",
CharSet = CharSet.Ansi, ExactSpelling = true,
CallingConvention = CallingConvention.Cdecl)]
private static extern System.IntPtr touppercase(string postData);
在我的应用程序这个调用看起来像
string sTest2 = Marshal.PtrToStringAnsi(to_uppercase(sTest));
然而sTest2最终只是一个随机字符串。
我添加了一个测试函数给具有相同参数的同一个dll,但是这个在本地分配了内存并且复制了字符串。这工作正常。为什么现在的原始版本有效?
注意:更新dll库本身不是一个选项。
调用此函数后sTest会发生什么?它会改变吗? – 2011-05-27 14:19:01
你为什么要宣布调用约定。默认情况下C#使用调用约定而不是标准约定(C/C++)。你已经改变了C库中的约定。如果C代码没有声明为默认值之外的其他值,则只需更改约定。 – 2011-05-27 14:41:29
@ramhound:明确指定导出函数的调用约定是最安全的。您不希望导出受'/ Gr'或'/ Gz'的影响。 – 2011-05-27 16:02:12