日期:2014-05-18  浏览次数:20761 次

新手求问:C#调用C++dll函数时返回值的问题
这是在C++头文件里头的声明
C/C++ code

extern "C" __declspec(dllexport) char* __stdcall getb(char * str);


这是函数的定义
C/C++ code

char * __stdcall getb(char * str)
{
    string strb(str);
    char * xstr = (char *)strb.c_str();
    return xstr;
}


这是C#里头函数导入的代码
C# code

    public class Utility
    {
        [DllImport("bb.dll", EntryPoint = "_getb@4", CallingConvention = CallingConvention.StdCall)]
        public static extern IntPtr getb(IntPtr inp);
    }


这里是C#里调用函数的代码
C# code

    string str = "AAAA";
    IntPtr trb = Utility.getb(Marshal.StringToBSTR(str));
    string b = Marshal.PtrToStringBSTR(trb);


觉得好奇怪,怎么调用函数的时候会提示异常:
未处理AccessViolationException
尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
而且如果把函数定义改成直接返回参数的指针,就没有问题:
C/C++ code

char * __stdcall getb(char * str)
{
    return str;
}


感觉应该是string里头出问题了吧~但是不知道错哪了,怎么修改,而且开始的想法不是只把char*放到string里头再得到char*,中间还有对那个string进行操作的。
请高手们帮忙找找错误~谢谢了~~

------解决方案--------------------

char * __stdcall getb(char * str)
{
string strb(str);
char * xstr = (char *)strb.c_str();
return xstr;
}


这样写有问题。
string strb(str);
strb创建在栈中,return xstr导致了strb的析构,strb中创建的字符串也随之丢失。
xstr指向strb创建的字符串,后果就是xstr指向已经释放的内存。

------解决方案--------------------
简单的,仅作传入参数用string,输出参数用StringBuilder。
[DllImport("bb.dll", EntryPoint = "_getb@4", CallingConvention = CallingConvention.StdCall)]
public static extern string getb(string str);

另LZ的C++写法不对,如可以返回std::string类型,不能返回指向函数内部临时变量的指针,这是危险的。