首先是C++的一个DLL文件
主要内容是:extern "C" __declspec(dllexport) char* getData();char DATA[1000];
double tmp;char* getData()
{
    tmp= 0.55;
    sprintf(DATA, "%f", tmp);
    return DATA;
}
C#来调用这个DLL
c#代码是:using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;namespace WindowsApplication3
{
    public partial class Form1 : Form
    {        [DllImport("WaferConePreSizing.dll")]
        public static extern string getData();        public Form1()
        {
            InitializeComponent();            string revStr = "";            revStr = getData();
        }
    }
}如果值是0.55就会报不能修改保护内存的错误,如果是0.45或者0.60就不会出问题
其他的值好像也都不会出问题。。
就这个 0.55期待高手解答。
谢谢~~~

解决方案 »

  1.   

        sprintf(DATA, "%lf", tmp);是不是要用 %lf 啊?
      

  2.   

    真是奇怪试试[DllImport("WaferConePreSizing.dll")]
            public static extern StringBuilder getData();
      

  3.   

    试试这里说的方法:You must return this as an IntPtr. Returning a System.String type from a PInvoke function requires great care. The CLR must transfer the memory from the native representation into the managed one. This is an easy and predictable operation.The problem though comes with what to do with the native memory that was returned from foo(). The CLR assumes the following two items about a PInvoke function which directly returns the string typeThe native memory needs to be freed 
    The native memory was allocated with CoTaskMemAlloc 
    Therefore it will marshal the string and then call CoTaskMemFree on the native memory blob. Unless you actually allocated this memory with CoTaskMemAlloc this will at best cause a crash in your application. In order to get the correct semantics here you must return an IntPtr directly. Then use Marshal.PtrToString* in order to get to a managed String value. You may still need to free the native memory but that will dependent upon the implementation of foo.
    extern "C" __declspec(dllexport) char *foo(void);IntPtr ptr = foo();
    string str = Marshal.PtrToStringAuto(ptr);
    参考:
    http://stackoverflow.com/questions/370079/pinvoke-for-c-function-that-returns-char
      

  4.   

    难道这里出的问题?
    tmp= 0.55;
        sprintf(DATA, "%f", tmp);
        return DATA;s试试先转换成float.
    sprintf(DATA, "%f", (float)tmp);
      

  5.   

    试一试:[DllImport("WaferConePreSizing.dll")]
    public static extern IntPtr getData();        public Form1()
            {
                InitializeComponent();            IntPtr ptr = getData();            string str = Marshal.PtrToStringAuto(ptr);
            }
      

  6.   


    不行的话,再试一试:
    [DllImport(_dllLocation)]
    [return : MarshalAs(UnmanagedType.LPStr)]
    public static extern string getData();
      

  7.   

    转成float也不行。。
    看来是转换完之后的字符数组作为返回值返回的时候出的问题。
    因为我用c++调用这个DLL是没有问题的。
      

  8.   

    [DllImport("WaferConePreSizing.dll")] 
    public static extern IntPtr getData();         public Form1() 
            { 
                InitializeComponent();             IntPtr ptr = getData();             string str = Marshal.PtrToStringAuto(ptr); 
            } 这个方法运行通过了,但是返回值是乱码,不是应该返回的那个
      

  9.   

       /// Return Type: char*
        [System.Runtime.InteropServices.DllImportAttribute("WaferConePreSizing.dll", EntryPoint="getData")]
    public static extern  System.IntPtr getData() ; 
      

  10.   

    17楼的内容是  利用IntPtr运行通过了,但是返回的是乱码。。
      

  11.   

    试一试: 
    IntPtr的防范修改一下试一试[DllImport("WaferConePreSizing.dll")] 
    public static extern IntPtr getData();         public Form1() 
            { 
                InitializeComponent();             IntPtr ptr = getData();             string tmp = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(ptr);
            } 参考:
    http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/df6ba613-43e7-4194-a687-15120e92ecf7/
     
     
     
      

  12.   

    难道 调用DLL的时候 都需要用这种托管的方式取数据吗?
      

  13.   

    c++调用的时候 0.55也是没有问题的。
    会不会是C#和C++在内存的使用上 有不同的地方导致的。
      

  14.   

    你这个c dll 代码是有问题的,你把一个const char [] 作为指针返回了 ,这是一个不好的做法,
    其次.net下你用string 封送 ,框架会把值赋给revStr以后 ,会试图释放这个指针,结果出现了意想不到的情况。
    做好的做法是传入char* 引用,或者
    在c++dll里
     tmp= 0.55;
        sprintf(DATA, "%f", tmp);
        return _strdup(DATA);
      

  15.   


    很有道理试了一下,果然也是可以的。
    那问题就出在了,赋值以后c#进行指针释放上了?上面说的最好的做法是传入char*引用。。是不是用StringBuilder作为输出参数传过去这种做法?如果是指针释放的话,为什么其他的数是没有问题的,只是0.55才会出现问题呢?
      

  16.   

    你的问题主要就是平台调用过程中的数据封送问题。楼上有人已经给出了正确的答案。但是如果只获得答案,不知道原理,以后遇到了此类问题还是不知道如何下手。如果你想系统学习如何进行数据封送,我推荐你阅读刚刚出版的新书:《精通.NET互操作P/Invoke,C++Interop和COM Interop》,这本书的第2章“数据封送”详细介绍了平台调用中的数据封送过程,非常详细,我就是读完后才搞清楚平台调用中的封送处理。 
    该书的官方网站: 
    www.interop123.com 豆瓣网信息: 
    http://www.douban.com/subject/3671497/