新手求助,这个函数怎样才能运行?

fws960211 2011-08-16 03:13:05
有一外部函数,如下定义:
int db_write_ex6 (unsigned short BlkNr, unsigned char DatType, unsigned
short StartNr, unsigned long * pAmount, unsigned long BufLen, unsigned
char * pWriteBuffer);
已经转换成C#封装,且可以正常运行。

//以下测试db_write_ex6
UInt16 BlkNr = 4;//data block号
Prodave6.DatType DType = Prodave6.DatType.BYPE ;//要读取的数据类型
UInt16 StartNr = 0;//起始地址号
UInt32 pAmount = 10;//需要读取类型的数量
UInt32 BufLen = 100;//缓冲区长度(字节为单位)
//参数:data block号、要写入的数据类型、起始地址号、需要写入类型的数量、缓冲区长度(字节为单位)、缓冲区
byte[] pWriteBuffer = new byte[15];

for (int i = 0; i < pWriteBuffer.Length; i++)
{
pWriteBuffer[i] = (byte)(i+1);

}
RetValue = Prodave6.db_write_ex6(BlkNr, DType, StartNr, ref pAmount, BufLen, pWriteBuffer);

以上写入BYTE值,运行正常。可我想写入实数值(DWORD),改Prodave6.DatType DType = Prodave6.DatType.WORD ;//要读取的数据类型
总也不成功。怎样才能写入实数值呢?只写一个数据也行呀。修改循环里面的pWriteBuffer[i] = (byte)(2.5)后,数据自动转成整型,2.5变成2了。给pWriteBuffer=2.5,运行函数出错。pWriteBuffer是BYTE型,晕呀,大家看看怎么办呢?



以下是运行结果:
变量 类型 初始值 当前值
var1 DWORD DW#16#0 DW#16#01020304
var2 WORD W#16#0 W#16#0506
v3 REAL 0.000000 1.023416e-034
v4 BYTE B#16#0 B#16#0B
v5 BYTE B#16#0 B#16#0C

...全文
188 14 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
fws960211 2011-08-19
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 fengws_sd 的回复:]

从你的运行结果来看:
var1 DWORD DW#16#0 DW#16#00000000
var2 DWORD DW#16#0 DW#16#00000440
DWORD是8位的,
而double val= 2.5 ;在C#中应该是16位的。所以造成VAR2异常。
修改 float val= 2.5F 试试。
[/Quote]
用了这个方法,成功解决了!原来是float的。写入后字节的高低位是相反的,我也成功解决好了。
pAmount是要读取或写入的数据数量,不是存取的字节数。
感谢stonespace和Fengws_sd!!
stonespace 2011-08-18
  • 打赏
  • 举报
回复
pAmount不应该是1,因为double有8个字节,DWORD只有4个字节,所以你应该写入2个DWORD,也就是pAmount应该等于2,
stonespace 2011-08-18
  • 打赏
  • 举报
回复
UInt16 BlkNr = 4;//data block号
Prodave6.DatType DType = Prodave6.DatType.DWORD ;//要读取的数据类型 只有BYTE,WORD DWORD三种类型。
UInt16 StartNr = 0;//起始地址号
UInt32 BufLen = 50;//缓冲区长度(字节为单位) //参数:data block号、要写入的数据类型、起始地址号、需要写入类型的数量、缓冲区长度(字节为单位)、缓冲区

double val= 2.5 ;
byte[] pWriteBuffer = new byte[50];
byte[] rData=BitConverter.GetBytes(val);
Array.Copy(rData,pWriteBuffer,rData.Length);

UInt32 pAmount = (rData.Length+3)/4;//需要读取类型的数量


RetValue = Prodave6.db_write_ex6(BlkNr, DType, StartNr, ref pAmount, BufLen, pWriteBuffer);
fengws_sd 2011-08-18
  • 打赏
  • 举报
回复
从你的运行结果来看:
var1 DWORD DW#16#0 DW#16#00000000
var2 DWORD DW#16#0 DW#16#00000440
DWORD是8位的,
而double val= 2.5 ;在C#中应该是16位的。所以造成VAR2异常。
修改 float val= 2.5F 试试。
stonespace 2011-08-17
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 fws960211 的回复:]
试过了,结果不对呀,哪里的问题呢?
var1 DWORD DW#16#0 DW#16#00000000
[/Quote]

一般来说,2.5不是DWORD类型,DWORD在C中定义为unsigned int,是4字节整数,
fws960211 2011-08-17
  • 打赏
  • 举报
回复
试过了,结果不对呀,哪里的问题呢?
var1 DWORD DW#16#0 DW#16#00000000
fws960211 2011-08-17
  • 打赏
  • 举报
回复
To stonespace:
看看我的代码是这样的:

UInt16 BlkNr = 4;//data block号
Prodave6.DatType DType = Prodave6.DatType.DWORD ;//要读取的数据类型 只有BYTE,WORD DWORD三种类型。
UInt16 StartNr = 0;//起始地址号
UInt32 pAmount = 1;//需要读取类型的数量
UInt32 BufLen = 50;//缓冲区长度(字节为单位) //参数:data block号、要写入的数据类型、起始地址号、需要写入类型的数量、缓冲区长度(字节为单位)、缓冲区

double val= 2.5 ;
byte[] pWriteBuffer = new byte[50];
byte[] rData=BitConverter.GetBytes(val);
Array.Copy(rData,pWriteBuffer,rData.Length);

RetValue = Prodave6.db_write_ex6(BlkNr, DType, StartNr, ref pAmount, BufLen, pWriteBuffer);

运行结果:
var1 REAL 0.000000e+000 0.0
var2 REAL 0.000000e+000 0.0

到底出错在什么地方呀?给个出路吧!



附:db_write_ex6
The db_write_ex6 writes a number of data words that are located in a defined
storage area (buffer) in the PG/PC into a data block in the AS.
It is possible to read out data words word-by-word/double word-by-word (pAmount
= 1) or block-by-block (pAmount > 1) with db_write_ex6.
int db_write_ex6 (unsigned short BlkNr, unsigned char DatType, unsigned
short StartNr, unsigned long * pAmount, unsigned long BufLen, unsigned
char * pWriteBuffer);
Parameters
BlkNr
[in] Number of the data block
DatType
[in] Type of data to be written:
0x02 = BYTE, 0x04 = WORD, 0x06 = DWORD default: DatType = 0x02
StartNr
[in] Start number of the first data word / double word to be written
pAmount
[in/out] The number of the data words / data double words to be written
BufLen
[in] Length of the transfer buffer provided by the user in bytes.
pWriteBuffer
[out] pointer on transfer buffer for the data words / double words alreadywritten

sdl2005lyx 2011-08-16
  • 打赏
  • 举报
回复
3楼的方法应该可以解决你的问题
fws960211 2011-08-16
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 stonespace 的回复:]
从表面上看,DWORD不是WORD类型,你的代码中似乎是要操作double型,

可以用BitConverter.GetBytes把数据转换为Byte[],

byte[] rData=BitConverter.GetBytes(2.5);
Array.Copy(rData,pWriteBuffer,rData.Length);
[/Quote]
修改为这样:
UInt16 BlkNr = 4;//data block号
Prodave6.DatType DType = Prodave6.DatType.DWORD ;//要读取的数据类型
UInt16 StartNr = 0;//起始地址号
UInt32 pAmount = 4;//需要读取类型的数量
UInt32 BufLen = 100;//缓冲区长度(字节为单位)
//参数:data block号、要写入的数据类型、起始地址号、需要写入类型的数量、缓冲区长度(字节为单位)、缓冲区
byte[] pWriteBuffer = new byte[15];

byte[] rData=BitConverter.GetBytes(2.5);
Array.Copy(rData,pWriteBuffer,rData.Length);
RetValue = Prodave6.db_write_ex6(BlkNr, DType, StartNr, ref pAmount, BufLen, pWriteBuffer);
执行结果:
var1 DWORD DW#16#0 DW#16#00000000
var2 DWORD DW#16#0 DW#16#00000440
v3 REAL 0.000000e+000 0.0
v4 BYTE B#16#0 B#16#00

fws960211 2011-08-16
  • 打赏
  • 举报
回复
是通过DLLIMPORT调用的。没有其它操作。
stonespace 2011-08-16
  • 打赏
  • 举报
回复
从表面上看,DWORD不是WORD类型,你的代码中似乎是要操作double型,

可以用BitConverter.GetBytes把数据转换为Byte[],

byte[] rData=BitConverter.GetBytes(2.5);
Array.Copy(rData,pWriteBuffer,rData.Length);

sdl2005lyx 2011-08-16
  • 打赏
  • 举报
回复
楼主,把你“已经转换成C#封装”的代码贴出来,看看是否是互操作的问题。。。
LMAOhuaNL 2011-08-16
  • 打赏
  • 举报
回复
晕了(*^__^*)

111,096

社区成员

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

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

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