请教一个DLL方法如何传递参数?

wohaorende 2010-11-15 07:53:39
跟大家请教个问题。VB2008如何开辟一个很大的内存空间,然后把内存空间的地址传递过去?
我要调用的DLL文件的方法是这样说明的。
extern "C" DLLexport int _stdcall ReadVersion
(char *str_version,
char *strIPAddress,
unsigned int outtime,
unsigned int num);
功能: 计数器设置函数.
* 在 VC 里表示指针,需要采用参数的地址传递。
输入参数:strIPAddress:仪器的 IP地址,比如:”192.168.1.198”。
outtime:超时时间,单位 ms,一般设置 100ms 以上。
num:连接次数为 num+1,用于超时后再重新连接 num 次,取 1-255,一般设为 3。
输出参数:str_ version:保存返回的模块软件版本字符,该空间要求不少于 20 个字符。
返回值: 如果成功返回 1,不存在该 IP 返回-1,设置参数错误返回 0,连接 num+1 次后还超时返回 2。
我的VB代码是这么写的。
Declare Function ReadVersion Lib "AsmDLL" (ByRef str_version As String, ByRef strIPAddress As String, ByVal outtime As Long, ByVal num As Long) As Integer
Private Sub ButRead_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButRead.Click
Dim ip As String
ip = "192.168.1.198"
Dim strversion(0 To 100) As String
MsgBox(ReadVersion(strversion(0), ip, 100, 3))
End Sub
总是返回2.提示我超时,我该如何传参数?

我还参考了C#的代码,如下:
[DllImport("AsmDll.dll")]
public extern static int ReadVersion(StringBuilder str_version, string strIPAddress, int outtime, int num);

//ReadVersion
private void btnReadVersion_Click(object sender, EventArgs e)
{
StringBuilder str_name = new StringBuilder(32); //定义buff
string address = "192.168.1.198";
int u = ReadVersion(str_name, address, 100, 1);
MessageBox.Show(u.ToString());
}
返回1.证明可以正常使用。


我还参考了VB6.0的代码。如下:
Declare Function ReadVersion Lib "AsmDLL" (ByVal str_version As String, ByVal strIPAddress As String, ByVal outtime As Long, ByVal num As Long) As Integer

Private Sub Command6_Click()
Dim strversion As String * 20
Text6.Text = ReadVersion(strversion, "192.168.1.198", 100, 3)
Text6.Text = strversion
End Sub
也可以正常使用。


用VB2008总是超时。我要晕了。不知道如何传递参数!
在线求教!在线等!
...全文
438 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
wohaorende 2010-11-16
  • 打赏
  • 举报
回复

public extern static int GetData( short[] pData, int nCount, string strIPAddress, int outtime, int num);
private void btnGetData_Click(object sender, EventArgs e)
{
short[] data = new short[16];//{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
string address = "192.168.1.198";
int u = GetData( data, 16, address, 100, 3);
MessageBox.Show(u.ToString());

}

C#代码是这样的,我使用了不好用啊。
函数名称不一样。GetData和ReadSerialData的参数类型不同。
ReadSerialData的是char *serialdata
机器人 2010-11-16
  • 打赏
  • 举报
回复
Dim serial_num1 As Short() = New Short(15) {}

我看你用另外一个C#调用的时候,是初始化为16个元素的数组,不是这样吗?
wohaorende 2010-11-16
  • 打赏
  • 举报
回复
采用了您的声明方法返回错误:
尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
Declare Function ReadSerialData Lib "AsmDll" (ByVal serial_num As Short(), ByVal serialdata As StringBuilder, ByVal len As Integer, ByVal strIPAddress As String, ByVal outtime As Integer, ByVal num As Integer) As Integer
代码如下:
If 1 = CreateReadSocket(ip) Then
Dim serial_num1 As Short() = New Short(15) {}
Dim data As StringBuilder = New StringBuilder(1024)
Dim len As UInteger : len = 0
If ReadSerialData(serial_num1, data, len, ip, 1, 0) = 1 Then
If len > 0 Then
MsgBox("读取成功")
End If
End If
Else
MsgBox("CreateReadSocket失败")
End If

我还采用了另外一种写法,因为函数的传参是让这样传的。
extern "C" DLLexport int _stdcall ReadSerialData
(unsigned short serial_num,
char *serialdata,
unsigned int *len,
char *strIPAddress,
unsigned int outtime,
unsigned int num);

Declare Function ReadSerialData Lib "AsmDll" (ByVal serial_num As Short, ByVal serialdata As Char(), ByVal len As Integer, ByVal strIPAddress As String, ByVal outtime As Integer, ByVal num As Integer) As Integer
If CreateReadSocket(ip) = 1 Then
Dim data As Char() = New Char(1024) {}
Dim sun As Short
Dim len As Integer
If ReadSerialData(sun, data, len, ip, 300, 3) = 1 Then
If len > 0 Then
MsgBox("读取成功")
End If
End If
Else
MsgBox("CreateReadSocket失败")
End If
结果报错:
尝试读取或写入受保护的内存。这通常指示其他内存已损坏。

我翻阅DLL文档关于C++的使用实例,发现他是这么用的。
DWORD WINAPI Rs485TestStartRead(LPVOID lpParam)
{
unsigned int len = 0;
unsigned short serialnum;
char buff[1124]; //

ResetEvent(h_485);//把USB操作置为无信号状态,不可以中断USB操作
CloseReadSocket(SK6000_Ipaddr);
int back = CreateReadSocket(SK6000_Ipaddr);

while(!b485Stop)
{
len = 0;
int back = ReadSerialData(&serialnum,
buff,
&len,
SK6000_Ipaddr,
1, //这两个参数设置为1和0间隔时间最小,必须尽快返回
0);
if(len>0)
{
//buff[0] = 'A';//
buff[len] = 0;//加结束符
Rs485TestForm->UartReadMemo->Lines->Add(buff);
len = 0;
}
/*
if(WaitForSingleObject(h_485SendStart,0) == WAIT_OBJECT_0) //判断是否需要发送数据
{
Back_485Send = SendSerialData(SerialNum_485Send,
Array_485Send,
Lenght_485Send,
SK6000_Ipaddr,
Rs485Test_Outtime,
Rs485Test_Outnum);

ResetEvent(h_485SendStart);//手动把发送置为无信号状态
SetEvent(h_485SendEnd);//把发送完置为有信号状态
}
*/

}
CloseReadSocket(SK6000_Ipaddr);
SetEvent(h_485);//把USB操作置为有信号状态,可以中断USB操作
return TRUE;
}


这个我就不知道怎么转换成VB了。帮忙一下!谢谢。
[Quote=引用 14 楼 fangxinggood 的回复:]

Declare Function ReadSerialData Lib "AsmDll" (ByVal serial_num As Short(), ByVal serialdata As StringBuilder, ByVal len As Integer, ByVal strIPAddress As String, ByVal outtime As Integer, ByVal num A……
[/Quote]
机器人 2010-11-16
  • 打赏
  • 举报
回复
Declare Function ReadSerialData Lib "AsmDll" (ByVal serial_num As Short(), ByVal serialdata As StringBuilder, ByVal len As Integer, ByVal strIPAddress As String, ByVal outtime As Integer, ByVal num As Integer) As Integer
wohaorende 2010-11-16
  • 打赏
  • 举报
回复
补充一下,该方法执行前要设置一个IP地址ReadSerialData我已经设置提示成功。
wohaorende 2010-11-16
  • 打赏
  • 举报
回复
帮忙看看我上面的问题,谢谢。[Quote=引用 10 楼 fangxinggood 的回复:]

outtime, num 这两个参数,在你的C#里是int型的,VB.NET也应该是Integer的。

VB6里的Long位数和VB.NET里的Integer是一样的。
[/Quote]
wohaorende 2010-11-16
  • 打赏
  • 举报
回复
你的回答解决了我的问题。现在请教下一步。我的DLL文件是这样说明的。

43、extern "C" DLLexport int _stdcall ReadSerialData
(unsigned short *serial_num,
char *serialdata,
unsigned int *len,
char *strIPAddress,
unsigned int outtime,
unsigned int num);
功 能: 串行总线接收数据函数。建议最好在程序里开一个独立接收数据线程进行侦听,
保证协议转换模块发送来的数据能被及时接收。
输入参数:strIPAddress:仪器的 IP地址,比如:”192.168.1.201”。
outtime:超时时间,单位 ms,一般设置 100ms 以上。
num:连接次数为 num+1,用于超时后再重新连接 num 次,取 1-255,一般设为 3。
输出参数:serial_num:返回接收的数据包对应的串行总线号,目前可以分别为 0、1。
serialdata:接收数据的数据地址。需要用户自己创建一个足够大的空间,并且
把该空间的地址赋给该参数。
len:返回接收到的数据长度。
返 回 值: 如果成功返回 1,不存在该 IP 返回-1,设置参数错误返回 0,连接 num+1 次后还
超时返回 2。

44、extern "C" DLLexport int _stdcall CreateReadSocket(char *strIPAddress);
功 能: 创建串行总线接收数据函数 ReadSerialData()的 Socket,必须在调用
ReadSerialData()函数之前调用一次该函数,并且要求
CreateReadSocket(),CloseReadSocket()与 ReadSerialData()在同一个线程
里。
输入参数:strIPAddress:仪器的 IP地址,比如:”192.168.1.201”。
输出参数:无。
返 回 值: 如果成功返回 1,不成功返回-1。
我是这样写VB.NET代码的。
Declare Function ReadSerialData Lib "AsmDll" (ByVal serial_num As Short, ByVal serialdata As StringBuilder, ByVal len As Integer, ByVal strIPAddress As String, ByVal outtime As Integer, ByVal num As Integer) As Integer
Declare Function CreateReadSocket Lib "AsmDLL" (ByVal strIPAddress As String) As Integer
If CreateReadSocket(ip) = 1 Then
Dim data1 As New StringBuilder(1024)
Dim sun As Short
Dim len As Integer
If ReadSerialData(sun, data1, len, ip, 300, 3) = 1 Then
If len > 0 Then
MsgBox("读取成功")
End If
End If
Else
MsgBox("CreateReadSocket失败")
End If

返回的是2,超时。不知道何故,我参考了VB6.0的代码,函数名不一样,因为不是一个设备,但是参数类型差不多。函数说明如下:
12、extern "C" DLLexport int _stdcall GetData
(short *pData,
unsigned int nCount,
char *strIPAddress,
unsigned int outtime,
unsigned int num);
功 能:单次采集。读取的数据是连续的,数据量是可以为 1-2
32

输入参数:nCount
读取采集数据个数(每个采集数据是 16bit) 。
strIPAddress:同上一个函数相同参数。
outtime:同上一个函数相同参数。
num:同上一个函数相同参数。
输出参数:pData
存放数据数组的地址,这个地址由应用程序给,存放数据的空间也由应用程序申
请,要读多少数据,就开多大空间。数据存放次序按多路开关切换采集的次序。
也就是每次读第一个数是开始通道,排放次序是:开始通道数据…结束通道数据,
开始通道数据…结束通道数据,…。
返 回 值: 如果成功返回 1, 不存在该 IP 返回-1, 失败返回 0, 连接 num+1次超时后返回-2。
特别说明:以从采集卡读上来的数据是 16 位有符号的整型为例,如果要转换为对应的电压
值,根据设定的输入范围,计算公式如下:
+/-10V: 电压 V = 10.0*Vhex/0x7fff;
+/-5V: 电压 V = 5.0*Vhex/0x7fff;
+/-2.5V: 电压 V = 2.50*Vhex/0x7fff;
0-10V: 电压 V = 5.0*Vhex/0x7fff+ 5.0;
0-5V: 电压 V = 2.5*Vhex/0x7fff+ 2.5;
0-2.5V: 电压 V = 1.25*Vhex/0x7fff+ 1.25;
其中:1、Vhex 为有符号的 16 位或 12 位整型采集卡数据;
2、如果采集卡为 12 位,比如SK1231,那么把 0x7fff 改为 0x7ff。
以下相近函数 GetCountData、GetCountDataEx 等读取的 A/D 数据电压值转换计算方法
跟这相同。

VB6.0代码如下:
Declare Function GetData Lib "AsmDLL" (ByRef pData As Integer, ByVal nCount As Long, ByVal strIPAddress As String, ByVal outtime As Long, ByVal num As Long) As Integer

Dim data(1 To 2000) As Integer
Do
For i = 1 To 999
data(i) = 0
Next i
Text8.Text = GetData(data(1), 10, "192.168.1.198", 200, 3)
同时C#代码如下:
public extern static int GetData( short[] pData, int nCount, string strIPAddress, int outtime, int num);
private void btnGetData_Click(object sender, EventArgs e)
{
short[] data = new short[16];//{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
string address = "192.168.1.198";
int u = GetData( data, 16, address, 100, 3);
MessageBox.Show(u.ToString());
double[] temp = new double [16];//{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
double count=0, avg=0;
for (int i = 0; i < data.Length; i++)
{
temp[i] = data[i]*10.0/0x7fff; //转换为电压
count += temp[i];
}
avg = count / 16;
MessageBox.Show(avg.ToString());
}



我该声明什么样的参数,如何传参数?
[Quote=引用 8 楼 ncqingchuan1976 的回复:]

声明改为这样
Declare Function ReadVersion Lib "AsmDLL" (Byval str_version As StringBuilder, ByVal strIPAddress As String, ByVal outtime As Long, ByVal num As Long) As Integer
VB.NET code





调用
VB.N……
[/Quote]
机器人 2010-11-15
  • 打赏
  • 举报
回复
outtime, num 这两个参数,在你的C#里是int型的,VB.NET也应该是Integer的。

VB6里的Long位数和VB.NET里的Integer是一样的。
ncqingchuan1976 2010-11-15
  • 打赏
  • 举报
回复
声明改为这样

Declare Function ReadVersion Lib "AsmDLL" (Byval str_version As StringBuilder, ByVal strIPAddress As String, ByVal outtime As Integer, ByVal num As Integer) As Integer

调用

Dim str_name As StringBuilder = new StringBuilder(32) '定义buff
Dim address as string = "192.168.1.198"
Dim u As int = ReadVersion(str_name, address, 100, 1)
MessageBox.Show(u.ToString)
ncqingchuan1976 2010-11-15
  • 打赏
  • 举报
回复
声明改为这样
Declare Function ReadVersion Lib "AsmDLL" (Byval str_version As StringBuilder, ByVal strIPAddress As String, ByVal outtime As Long, ByVal num As Long) As Integer




调用

Dim str_name As StringBuilder = new StringBuilder(32) '定义buff
Dim address as string = "192.168.1.198"
Dim u As int = ReadVersion(str_name, address, 100, 1)
MessageBox.Show(u.ToString())

wohaorende 2010-11-15
  • 打赏
  • 举报
回复
看看我的结贴率,看看我的问题分,没事儿上来说两句,就当我散分了!
wohaorende 2010-11-15
  • 打赏
  • 举报
回复
Dim str_name As New StringBuilder(32)
'定义buff
Dim address As String = "192.168.1.198"
Dim u As Integer = ReadVersion(str_name, address, 100, 1)
MessageBox.Show(u.ToString())
转换完是这个样子的。十分感谢,但是还是超时。。[Quote=引用 5 楼 asdfy 的回复:]

http://www.developerfusion.com/tools/convert/csharp-to-vb/
[/Quote]
古今多少事 2010-11-15
  • 打赏
  • 举报
回复
http://www.developerfusion.com/tools/convert/csharp-to-vb/
wohaorende 2010-11-15
  • 打赏
  • 举报
回复
这么使用转换工具?[Quote=引用 3 楼 asdfy 的回复:]

C#代码能用就用转换工具转到VB.NET试试啊。
[/Quote]
古今多少事 2010-11-15
  • 打赏
  • 举报
回复
C#代码能用就用转换工具转到VB.NET试试啊。
wohaorende 2010-11-15
  • 打赏
  • 举报
回复
我看到你的MARK了。[Quote=引用 1 楼 xiachufeng_ 的回复:]

MARK
[/Quote]

16,554

社区成员

发帖
与我相关
我的任务
社区描述
VB技术相关讨论,主要为经典vb,即VB6.0
社区管理员
  • VB.NET
  • 水哥阿乐
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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