C#调用C++ dll 参数是结构体数组,参数调用问题 求大神支招

hediping9811 2014-08-05 01:38:39
#define RTDB_TAGNAME_LENGTH 48 //测点点名最大长度

//************************************
//给已有记录点插入数据结构体
//************************************
typedef struct InsertData_struct{
int type; //为0则为开关量,为1则为摸拟量
int status; //写入点记录的状态
double value; //写入点记录的值
long time; //写入点记录的时间,秒
char pointName[RTDB_TAGNAME_LENGTH]; //写入点的完整点名
}InsertData;



//************************************
//测点信息结构体
//************************************
//**************************************
//查询历史记录请求包的结构
//**************************************
typedef struct ReadHiDataRequest_struct{
long stTime; //查询点记录的开始时间,秒
long enTime; //查询点记录的结束时间,秒
long tPeriod; //查询点值的时间间隔,秒
int reqType; //查询的数据类型(原始=0,最大=1,最小=2,平均=3,快照=4)
char pointName[RTDB_TAGNAME_LENGTH]; //请求的完整点名
}ReadHiDataRequest;

//查询单个测点在给定的开始时间和结束时间之间的原始值

//查询单个测点在给定的开始时间和结束时间之间的原始值
typedef int (*pGetRawDataByTagName)(ReadHiDataRequest * pReadHiDataRequest, TagData * & pTagData,long * nCount);
pGetRawDataByTagName m_GetRawDataByTagName;

用C++调用如下 能获取到数据

void testGetRawDataByTagName()
{
long nCount = 0;
nCount = RTDB_MAX_DATACOUNT;
ReadHiDataRequest req;
TagData *tagDatas = NULL;

printf("\n开始输入测点");
printf("\nEnter tagname: ");
gets(req.pointName);
CTime ctime = CTime::GetCurrentTime();
time_t nowTime= ctime.GetTime();
req.stTime = nowTime-3600;//backSecond1;
req.enTime = nowTime;//-backSecond2;
req.tPeriod = 0;//nPeriod;
req.reqType =0;

int nRet = m_GetRawDataByTagName(&req,tagDatas,&nCount);

if (nRet == 0)
{
printf("获取测点原始数据数据成功!测点名 = %s,原始值数量%d\n",req.pointName,nCount);
for (int i = 0; i < nCount ; i++)
{
CTime ctime;
ctime = CTime(tagDatas[i].time);
printf("GetRawDataByTagName tagDatas[%d] Vlaue = %f time = %d-%d-%d %d:%d:%d status = %d\n"
,i, tagDatas[i].value,ctime.GetYear(),ctime.GetMonth(),ctime.GetDay(),ctime.GetHour(),ctime.GetMinute(),ctime.GetSecond(),
tagDatas[i].status);
}
}
else
{
printf("获取测点原始数据数据始值失败!\n");

}
m_RTDBFreePointer(tagDatas);

}


现在我要改成用C#调用;我自己写了种方法但是调用不出来,请大家帮忙看看是什么原因,我自己觉得还是 结构体参数传递不正确。返回的错误是一个接口内部错误。看不出来到底错在哪里。

[DllImport("RTDBInterface.dll", EntryPoint = "GetRawDataByTagName")]
private static extern int GetRawDataByTagName1(ReadHiDataRequest preq, ref IntPtr ptrReslut, ref long nCount);
long nCount = 0;
nCount = RTDB_MAX_DATACOUNT;

ReadHiDataRequest req = new ReadHiDataRequest();
TagData[] tagDatas = new TagData[nCount];
for (int i = 0; i < nCount; i++)
{
tagDatas[i] = new TagData ();

}
IntPtr ptrRsult = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(TagData)) * Convert.ToInt32(nCount));

DateTime dtBeginTime = this.dtpBeginTime.Value;
DateTime dtEndTime = this.dtpEndTime.Value;

DateTime dt = new DateTime(1970, 1, 1);
TimeSpan d1 = DateTime.Parse(dtBeginTime.ToString()) - dt;
TimeSpan d2 = DateTime.Parse(dtEndTime.ToString()) - dt;
req.stTime = d1.Ticks / 10000000 - 3600;//backSecond1;
req.enTime = d1.Ticks / 10000000;//-backSecond2;
req.tPeriod = 0;//nPeriod;
req.reqType = 0;
req.pointName = strCedian;

int nRet = GetRawDataByTagName1(req, ref ptrRsult, ref nCount);
if (nRet == 0)
{
MessageBox.Show("sucess!");
Bussiness bus = new Bussiness();
string strShordID = bus.getShortID(strCedian.ToString());
for (int i = 0; i < nCount; i++)
{
double seconds = tagDatas[i].time + 28800;
double secs = Convert.ToDouble(seconds);
DateTime dtTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Unspecified).AddSeconds(secs);
if (bus.IsExist(strShordID, dtTime))
{
bus.Update(strShordID, tagDatas[i].value, dtTime);
}
else { bus.Insert(strShordID, tagDatas[i].value, DateTime.Now, dtTime, tagDatas[i].status); }
}
}
else { MessageBox.Show("test1没有要导入的值!"); }
...全文
128 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
Saleayas 2014-08-05
  • 打赏
  • 举报
回复
long 的那个不要使用 MarshalAs,还是直接使用 int。 好像不配对。 我总觉微软这个做的不好。
hediping9811 2014-08-05
  • 打赏
  • 举报
回复
我试了下 还是有问题 能加您Q吗 我给你发个Demo 帮忙看看 十分感谢!
Saleayas 2014-08-05
  • 打赏
  • 举报
回复
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
        public struct ReadHiDataRequest
        {
            public int stTime;                //查询点记录的开始时间,秒
            public int enTime;                //查询点记录的结束时间,秒
	[MarshalAs(UnmanagedType.I4)] // 如果一定要用 long, 使用 MarshalAs 特性。
           public long tPeriod;                //查询点值的时间间隔,秒
            public int reqType;               //查询的数据类型(原始=0,最大=1,最小=2,平均=3,快照=4)
           [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 48)]
                        //public char[] pointName;        //请求的完整点名
            public string pointName;
        }
试试这个,另外一个看不到 C++ 的 签名。 但是,需要记住 long 在 C++ 中虽然叫长整数,但是是 32 位的,而在 C# 中是 64 位的。
hediping9811 2014-08-05
  • 打赏
  • 举报
回复
 [StructLayout(LayoutKind.Sequential)]
        public struct TagData
        {
            public double value;        //返回点的数值
            public long time;	    //返回点的时间,秒
            public int status;          //返回点的状态
        }
        //**************************************
        //查询历史记录请求包的结构
        //**************************************
        [StructLayout(LayoutKind.Sequential)]
        public struct ReadHiDataRequest
        {
            public long stTime;				//查询点记录的开始时间,秒
            public long enTime;				//查询点记录的结束时间,秒
            public long tPeriod;			    //查询点值的时间间隔,秒
            public int reqType;			   //查询的数据类型(原始=0,最大=1,最小=2,平均=3,快照=4)
            //[MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)]
                        //public char[] pointName;	    //请求的完整点名
            public string pointName;
        }
就是找不到那个参数弄错了!能帮忙猜测一下不?
Saleayas 2014-08-05
  • 打赏
  • 举报
回复
仔细检查结构的每一个参数。 ptrResult 是传出引用,需要在调用后,使用 Marshal 读取。因为这个内存在本地。 C++ long 的 C# 类型 是 int。C# 的 long 是更长的。

110,533

社区成员

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

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

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