如何通过引用发送字符串来修改该字符串的非托管C库?
我是与非托管库交互的新手。 我有一个非托管的C函数,它通过函数内的引用修改字符串。 我在从C#传递字符串并通过C函数修改它时遇到了麻烦。
这是C函数:
__declspec(dllexport) void __stdcall Test(char* name) { *name = "Bar"; }
这是C#DLL导入代码:
[DllImport(@"C:/blah/mylibrary.dll")] public extern static string Test(string name);
这是我用来调用函数的代码:
string s = "foo"; Test(s); //I want s to be "Bar" after the above line
我尝试在字符串参数上使用“ref”和“out”,并尝试将编组作为LPStr。 根据我的尝试,我得到一个错误
“作为String传入的指针不能位于进程地址空间的底部64K。”
要么
“试图读取或写入受保护的内存。这通常表明其他内存已损坏。”
我确定我只是用我的指针做一些愚蠢的事情。 有人可以帮我确定合适的C#代码,使“s”等于“bar”吗?
谢谢
你的C Test
function没有像你说的那样做。 它只需要一个局部变量( name
)并将其分配给一个固定的字符串。 要做你所说的,它必须在name
指向的地址中执行复制操作:
__declspec(dllexport) void __stdcall Test(char* name) { strcpy(name, "Bar"); }
当然,由于您的函数签名不正确(未指定缓冲区长度),因此这样的操作是等待的灾难。
考虑到C函数如上所述,那么您应该遵循Default Marshaling for Strings中指定的规则:
在某些情况下,必须将固定长度的字符缓冲区传递给非托管代码以进行操作。 在这种情况下,简单地传递字符串不起作用,因为被调用者无法修改传递的缓冲区的内容。 即使字符串是通过引用传递的,也无法将缓冲区初始化为给定大小。
解决方案是将StringBuilder缓冲区作为参数而不是字符串传递。 StringBuilder可以被被调用者解除引用和修改,前提是它不超过StringBuilder的容量。 它也可以初始化为固定长度。 例如,如果将StringBuilder缓冲区初始化为N的容量,则封送程序会提供大小为(N + 1)个字符的缓冲区。 +1表示非托管字符串具有空终止符而StringBuilder不具有空终止符。
所以你的DLL应该是这样的:
[DllImport(@"C:/blah/mylibrary.dll")] public extern static string Test(StringBuilder name);
并通过传递适当大小的StringBuilder
调用它:
StringBuilder foo = new StringBuilder(256); Test(foo);
如果添加长度参数,则会在C接口中添加一些完整性。
上述就是C#学习教程:如何通过引用发送字符串来修改该字符串的非托管C库?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/984999.html