纠结一个关于C# 调用C++DLL返回字符串的问题

cgyf520 2012-07-13 02:37:15
C# 调用一个C++DLL中的一个如下接口:
版本一
extern “C” __declspec(dllexport) BOOL Func(char* s1,char** s2)
{
string rt = "xxxxx";
memcpy(*s2,rt.c_str(),rt.length());
return false;
}

C#调用:
[DllImport(“MyDLL.dll", EntryPoint=" Func",CharSet=CharSet.ansi)];
public static bool Func(string s1,ref string s2);

问题来了,调用的时候有时会出现dll中内存被破坏,感觉是memcpy(*s2,rt.c_str(),rt.length());貌似这句有问题。
换成版本二:
extern “C” __declspec(dllexport) BOOL Func(char* s1,char** s2)
{
string rt = "xxxxx";
*s2 = rt.c_str();
return false;
}
内存的问题解决了,但是C#一侧返回的s2是乱码,上网查了下 C++的string.c_str()的生命周期同其string一致,个人感觉是的dll中函数返回导致其字符串生命结束。有人说出乱码是编码集的问题,应为dll不是用的unicode。然后版本三:
extern “C” __declspec(dllexport) BOOL Func(char* s1,char** s2)
{
string rt = "xxxxx";
*s2 = malloc(rt.length + 1);
memset(*s2,0,rt.length + 1);
memcpy(*s2,rt.c_str(),rt.length);
return false;
}
这样dll不会报内存错误,返回的字符串也正常,但是dll中申请的内存却没有释放,然后实验了一个版本四:
extern “C” __declspec(dllexport) BOOL Func(char* s1,char** s2)
{
*s2 = "xxxxxx";
return false;
}
同版本3一样,没有出问题,然后我想问的是在这次调用中*s2的内存哪里来的,dll申请的还是C#呢,什么时候释放,
*s2 = "xxxxxx";这句话怎么理解,运行时将"xxxxxx"拷贝到*s2已经分配好的内存空间?那岂不是会有越界的风险,
而且C#那边连续重复调用这个接口 *s2的内容都是第一次返回的内容,但是地址确不一致。而且我看上一次*s2地址里的内容页还在,感觉没有释放,那*s2到底该怎么处理呢。
...全文
501 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
dd_zhouqian 2012-07-13
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]

后版本三:
C/C++ code

extern “C” __declspec(dllexport) BOOL Func(char* s1,char** s2)
{
char * rt = null;
rt = malloc(1024);
memset(rt, 1024);
memcpy(rt, "xxxx");
memcpy(*s2,rt);
free(rt);
rt = null;
[/Quote]

感觉一般很少这样用,这个例子不好
dd_zhouqian 2012-07-13
  • 打赏
  • 举报
回复
后版本三:

extern “C” __declspec(dllexport) BOOL Func(char* s1,char** s2)
{
string rt = "xxxxx";
*s2 = malloc(rt.length + 1);
memset(*s2,0,rt.length + 1);
memcpy(*s2,rt.c_str(),rt.length);
free(rt);
rt = null;
return false;
}

qldsrx 2012-07-13
  • 打赏
  • 举报
回复
版本三和版本四申请的内存是非托管内存,需要由DLL自己释放,如果DLL不释放,则很可能内存泄漏。(非托管内存释放的方法自己去查,我也不清楚,根据引用计数来处理的,外部变量引用消失将释放)

版本一因为你对托管内存操作,而String是不允许改变大小的,因此操作失败,必须传递StringBuilder或ref sbyte。
Saleayas 2012-07-13
  • 打赏
  • 举报
回复
版本1,StringBuilder。
bdmh 2012-07-13
  • 打赏
  • 举报
回复
[DllImport("", CallingConvention = CallingConvention.Cdecl)]

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧