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里的结构体中的未知长度的数组,我该如何声明和调用?
{
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里的结构体中的未知长度的数组,我该如何声明和调用?
[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; } }
}
谢谢你的帮助,感觉你给的是我想要的,不过编译有问题
U_p += System.Runtime.InteropServices.Marshal.SizeOf(U_d);
U_p += System.Runtime.InteropServices.Marshal.SizeOf(U_d);
这一行代码,
错误 1 运算符“+=”无法应用于“System.IntPtr”和“int”类型的操作数
错误 2 无法将类型“int”隐式转换为“System.IntPtr”。存在一个显式转换(是否缺少强制转换?)
错误 1 运算符“+”无法应用于“System.IntPtr”和“int”类型的操作数
请帮忙,搞定立马结账,分不够我还有
U_p = new IntPtr(U_p.ToInt32() + System.Runtime.InteropServices.Marshal.SizeOf(U_d));
不好意思,昨天下班早。编译通过了,十分感谢。
只不过取出来的值,不是实际值,而是一串数字,好像是内存地址一样的。
icount我在dll里给赋值了常量也是这样,c#这边取icount都是内存地址
是这样的
我把C++结构体里,只减成
typedef struct
{
long int iCount;
}MyDLRes;
之后C#里,也改成只剩下iCount,值就是对的。不管用你的方法还是我的方法
但是我加上
typedef struct
{
double *XV;//这个就是C#里那个动态数组
long int iCount;
}MyDLRes;
返回来后,iCount就不对了,是内存地址了。iCount在DLL里是常量进行测试的,也是这样。
public static extern myKey MyEgcInit(string s);在C#中的定义不正确,你需要确定在C++中MyEgcInit函数返回是一个结构还是一个结构的指针。
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里的情况
如果需要传递结构体,我们的做法是现在C#里面定义好固定的内存空间,然后传递给C++的dll使用。