c++中结构体声明typedef struct
{
    double *XV;//这里就是关键了,长度不固定的,等会要new
    long int iCount;
   // char * myStrKey1;
   // char * myStrKey2;
}MyDLRes;C++中结构体的赋值MyDLRes pRes ;
……
pRes.XV = new double[len];//这个len是根据计算得来的
……
return pRes;之后C#中结构体声明public struct myKey
{
            public double[] myXY;
            public Int32 iCount;
            //public char []myStrKey1;
            //  public char []myStrKey2;
}
再之后C#中使用private const string _fileDll = "EGC.dll";
        [DllImport(_fileDll, EntryPoint = "MyEgcInit")]        public static extern myKey MyEgcInit(string s);        private void button1_Click(object sender, EventArgs e)
{
                    myKey myst = new myKey();
                    myst = MyEgcInit("1");
                        MessageBox.Show(myst.iCount.ToString());
     }
以上就是需求过程了,编译后调用,会提示说方法的类型签名与 PInvoke 不兼容如果我在两个结构体中去掉double数组部分,单纯的只用那个int iCount,是没有问题的请大家指点下,我在C#里要用到C++的DLL里的结构体中的未知长度的数组,我该如何声明和调用?

解决方案 »

  1.   

    myKey采用动态获取数据,myKey结构改为
            [StructLayout(LayoutKind.Sequential)]
            public struct myKey
            {
                IntPtr _xv;
                Int32 _iCount;            public double[] XV
                {
                    get
                    {
                        if (_iCount > 0)
                        {
                            double[] U_dArray = new double[_iCount];
                            IntPtr U_p = _xv;
                            for (int U_i = 0; U_i < _iCount; U_i++)
                            {
                                double U_d = (double)System.Runtime.InteropServices.Marshal.PtrToStructure(U_p, typeof(double));
                                U_dArray[U_i] = U_d;
                                U_p += System.Runtime.InteropServices.Marshal.SizeOf(U_d);
                            }
                            return U_dArray;
                        }
                        else
                        {
                            return new double[] { };
                        }
                    }
                }            public Int32 iCount { get { return _iCount; } }
            }
      

  2.   


    谢谢你的帮助,感觉你给的是我想要的,不过编译有问题
    U_p += System.Runtime.InteropServices.Marshal.SizeOf(U_d);
      

  3.   

    刚才发快了,我的意思是
    U_p += System.Runtime.InteropServices.Marshal.SizeOf(U_d);
    这一行代码,
    错误 1 运算符“+=”无法应用于“System.IntPtr”和“int”类型的操作数
    错误 2 无法将类型“int”隐式转换为“System.IntPtr”。存在一个显式转换(是否缺少强制转换?)
      

  4.   

    你可以把该行改为:U_p = U_p + System.Runtime.InteropServices.Marshal.SizeOf(U_d);
      

  5.   

    改成后,还是不行
    错误 1 运算符“+”无法应用于“System.IntPtr”和“int”类型的操作数
    请帮忙,搞定立马结账,分不够我还有
      

  6.   

    你VS是什么版本?2010下都可以编译通过,如果不是 Framework4.0 就用:
    U_p = new IntPtr(U_p.ToInt32() + System.Runtime.InteropServices.Marshal.SizeOf(U_d));
      

  7.   


    不好意思,昨天下班早。编译通过了,十分感谢。
    只不过取出来的值,不是实际值,而是一串数字,好像是内存地址一样的。
    icount我在dll里给赋值了常量也是这样,c#这边取icount都是内存地址
      

  8.   

    补充下,好像和你代码没有关系。
    是这样的
    我把C++结构体里,只减成
    typedef struct
    {
           long int iCount;
       }MyDLRes;
    之后C#里,也改成只剩下iCount,值就是对的。不管用你的方法还是我的方法
    但是我加上
    typedef struct
    {
        double *XV;//这个就是C#里那个动态数组
        long int iCount;
     }MyDLRes;
    返回来后,iCount就不对了,是内存地址了。iCount在DLL里是常量进行测试的,也是这样。
      

  9.   

    这有可能是[DllImport(_fileDll, EntryPoint = "MyEgcInit")]
     
            public static extern myKey MyEgcInit(string s);在C#中的定义不正确,你需要确定在C++中MyEgcInit函数返回是一个结构还是一个结构的指针。
      

  10.   


    extern "C" __declspec(dllexport) MyDLRes __stdcall MyEgcInit(char * f);MyDLRes pRes ; 
    …… 
    int len = 40000;
    pRes.XV = new double[len];//这个len是根据计算得来的 
    pRes.iCount = 40000;
    …… 
    return pRes; 
    以上是C++的DLL里的情况
      

  11.   

    刚刚查了一下我们的项目,没有返回结构体的。
    如果需要传递结构体,我们的做法是现在C#里面定义好固定的内存空间,然后传递给C++的dll使用。
      

  12.   

    你在C++中对MyDLRes赋值完成后,sizeof一下MyDLRes的长度,看是不是为8
      

  13.   

    8是指针和int的长度吧,结构体中不应该是指针,而是已知大小的数组。