各位大侠来帮忙看看,VB.net中如何调用这个 C 的标准 DLL~~~~

tony198512 2016-01-10 08:50:36
各位大侠,小弟由于某些原因需要使用 VB.NET 调用一个标准C 的 DLL,以下是该函数的描述级调用,我该如何翻译成VB的呢?
定义:
int32 s7_get_multiple_read_cnf(
void *od_ptr, /* In call */
ord16 *result_array, /* Returned */
ord16 *var_length_array, /* Call and Returned */
void *value_array /* Returned */
)

一个可运行的 C 程序例子:
static void my_get_multiple_read_cnf(ord32 cp_descr)
{ int32 ret;
ord16 result[2],var_length[2];
ord8 data_buffer[4]; /* four Byte are necessary for reading two MWORD */
ord8 *value_ptr[2];

/* initialize arrays */
result[0] = S7_RESULT_OBJ_NOT_EXISTS;
result[1] = S7_RESULT_OBJ_NOT_EXISTS;
var_length[0] = 2;
var_length[1] = 2;
value_ptr[0] = &data_buffer[0]; /* set first pointer to begin of buffer */ /问题点
value_ptr[1] = &data_buffer[2]; /* set sec. pointer to offset 2 */ /问题点

if((ret=s7_get_multiple_read_cnf(NULL,result,var_length,value_ptr))!=S7_OK)
{
my_exit(cp_descr,"Error s7_get_multiple_read_cnf",ret);
}
}

问题来了,实际上 value_ptr的第0和第1个元素分别存的是 data_buffer[0] 和 data_buffer[2]的地址,然后将value_ptr作为参数传送给 DLL 中,但是我试了不是报错就是返回值 Value_ptr 中只有一个值。VB.net中该如何处理呢??重分相赠,各位大侠快来呀~~
...全文
1764 56 打赏 收藏 转发到动态 举报
写回复
用AI写文章
56 条回复
切换为时间正序
请发表友善的回复…
发表回复
tony198512 2016-01-18
  • 打赏
  • 举报
回复
手机不能结贴,晚点再来结贴
tony198512 2016-01-17
  • 打赏
  • 举报
回复
最终解决了,用COPYMEMORY是可以的,终于解决了
一笑拔剑 2016-01-16
  • 打赏
  • 举报
回复
gc系统回收的没法控制的嘛 copymemory 本来就是做这事的 另外你既然c会写,可以用c重新封装下那个dll啊
tony198512 2016-01-15
  • 打赏
  • 举报
回复
引用 45 楼 Tiger_Zhao的回复:
你C代码的测试结果呢?
先要知道真正的正确结果才能转化出正确的代码,而不是往你臆想的正确结果去套。
C是正常的,返回值写到了,data_buffer数组中,但是在VB里 data_buffer的内存地址会变。 另外我试了,即便没有这个API函数直接定义一个空数组连续使用GC读两次,每次读到的值是不一样的
Tiger_Zhao 2016-01-15
  • 打赏
  • 举报
回复
你C代码的测试结果呢?
先要知道真正的正确结果才能转化出正确的代码,而不是往你臆想的正确结果去套。
tony198512 2016-01-15
  • 打赏
  • 举报
回复
引用 42 楼 舉杯邀明月的回复:
既然 .NET 中的这些变量地址“无法自己管控”, 那value_buffer() 和 value_array() 用到的内存区,全部用API来申请和释放。 相当于在 C++中用 New和Delete 来处理……
而且这个API函数是不会自己分配空间的,我试过了,必须给它一个地址它才不会报错。
tony198512 2016-01-15
  • 打赏
  • 举报
回复
引用 42 楼 舉杯邀明月的回复:
既然 .NET 中的这些变量地址“无法自己管控”, 那value_buffer() 和 value_array() 用到的内存区,全部用API来申请和释放。 相当于在 C++中用 New和Delete 来处理……
什么意思呢?VB中我该怎么做呢?昨天晚上查了一晚上也没查到有意义的信息。。
舉杯邀明月 2016-01-15
  • 打赏
  • 举报
回复
既然 .NET 中的这些变量地址“无法自己管控”, 那value_buffer() 和 value_array() 用到的内存区,全部用API来申请和释放。 相当于在 C++中用 New和Delete 来处理……
tony198512 2016-01-15
  • 打赏
  • 举报
回复
copymemory 可以直接读取某内存地址中的数值吗?
舉杯邀明月 2016-01-15
  • 打赏
  • 举报
回复
引用 44 楼 ststst1231 的回复:
[quote=引用 42 楼 舉杯邀明月的回复:]既然 .NET 中的这些变量地址“无法自己管控”, 那value_buffer() 和 value_array() 用到的内存区,全部用API来申请和释放。 相当于在 C++中用 New和Delete 来处理……
而且这个API函数是不会自己分配空间的,我试过了,必须给它一个地址它才不会报错。[/quote] 我说是说的用API申请好内存空间(GlobalAlloc、GlobalFree等4个),给你的这个API用啊。 但有个问题就是,你能不能把返回的数据通过CopyMemory,“转移”到你自己的变量中去。
tony198512 2016-01-15
  • 打赏
  • 举报
回复
而且为什么在执行了GC以后,数组的内存地址会发生变化呢??
tony198512 2016-01-15
  • 打赏
  • 举报
回复
这个好复杂啊。。。用GC可以不改变数组的内存地址吗
Tiger_Zhao 2016-01-15
  • 打赏
  • 举报
回复
从《NET中使用CopyMemory》学来的
Imports System.Runtime.InteropServices

Module Module1

<StructLayout(LayoutKind.Sequential)> _
Public Class ByteArray2
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=2)> Public item() As Byte

Public Sub New()
ReDim Me.item(1)
End Sub
End Class

<StructLayout(LayoutKind.Sequential)> _
Public Class ByteArray8
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=8)> Public item() As Byte

Public Sub New()
ReDim Me.item(7)
End Sub
End Class

<StructLayout(LayoutKind.Sequential)> _
Public Class IntArray2
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=2)> Public item() As Integer

Public Sub New()
ReDim Me.item(1)
End Sub
End Class

Sub Main()
Dim value_buffer As New ByteArray2
Dim value_array As New IntArray2
Dim bytes As New ByteArray8

Console.WriteLine("value_buffer : Size = {0} : Count = {1}", Marshal.SizeOf(value_buffer), value_buffer.item.Count)
Console.WriteLine("value_array : Size = {0} : Count = {1}", Marshal.SizeOf(value_array), value_array.item.Count)
Console.WriteLine("bytes : Size = {0} : Count = {1}", Marshal.SizeOf(bytes), bytes.item.Count)

'申请一块内存pBuffer'
Dim pBuffer As IntPtr = Marshal.AllocHGlobal(2)
Debug.Assert(pBuffer.ToInt32 > 0, "地址不过2G.")
Console.WriteLine("pBuffer : {0:X8}", pBuffer.ToInt32)

'把value_array的指针执行前面的内存块'
For i = 0 To 1
value_array.item(i) = pBuffer.ToInt32 + i * 1
Next i

'把value_array复制到另外一块内存pArray'
Dim pArray As IntPtr = Marshal.AllocHGlobal(8)
Console.WriteLine("pArray : {0:X8}", pArray.ToInt32)
Marshal.StructureToPtr(value_array, pArray, True)

'查看pArray的内容'
Marshal.PtrToStructure(pArray, bytes)
Console.WriteLine(BitConverter.ToString(bytes.item))

'用pArray调用API'

'把返回的数据复制回数组'
Marshal.PtrToStructure(pBuffer, value_buffer)
Marshal.PtrToStructure(pArray, value_array)

Marshal.FreeHGlobal(pBuffer)
Marshal.FreeHGlobal(pArray)

Console.ReadLine()
End Sub

End Module

value_buffer : Size = 2 : Count = 2
value_array : Size = 8 : Count = 2
bytes : Size = 8 : Count = 8
pBuffer : 01364110
pArray : 01339F90
10-41-36-01-11-41-36-01
tony198512 2016-01-15
  • 打赏
  • 举报
回复
这个你试了吗??我试过用2个GC读取 还是会变。。
Tiger_Zhao 2016-01-15
  • 打赏
  • 举报
回复
[Quote=引用 40 楼 user 的回复:]
  For i = 0 To read_para_index
var_length_array(i) = 1
GC = GCHandle.Alloc(value_buffer(i), GCHandleType.Pinned)
value_array(i) = GC.AddrOfPinnedObject.ToInt32
Next i

value_buffer() 的内存地址会变化[/Quote]
应该是你只用了一个GC变量,那么后一个赋值的时候前一个可能就自动释放了。
等于只有最后一个是钉住的。

而且.NET中中Byte也是Object,Byte数组的两个成员并不是紧邻的两字节。
象你C代码中一个把 data_buffer[0]、data_buffer[1] 作为一个 WORD 进行内存复制是不行的。
Imports System.Runtime.InteropServices

Module Module1

Sub Main()
Dim value_buffer(1) As Byte
Dim value_array(1) As Integer
Dim GC(1) As GCHandle
Dim bytes(24 - 1) As Byte

For i = 0 To 1
GC(i) = GCHandle.Alloc(value_buffer(i), GCHandleType.Pinned)
value_array(i) = GC(i).AddrOfPinnedObject.ToInt32
Console.WriteLine("{0:X8}", value_array(i))
Next i

'调用API'

For i = 0 To 1
GC(i).Free()
Next

Console.ReadLine()
End Sub

End Module

地址差了好远
015BFB88
015CA18C


还有……
tony198512 2016-01-14
  • 打赏
  • 举报
回复
又有新的发现,并不是执行了 DLL 中的函数后 数组 value_buffer() 的内存地址会变化,而是执行了 GCHandle.Alloc(value_buffer(i), GCHandleType.Pinned) 之后 value_buffer() 数组的内存地址就会变化。。该如何处理呢???
tony198512 2016-01-14
  • 打赏
  • 举报
回复
  For i = 0 To read_para_index
            var_length_array(i) = 1
            GC = GCHandle.Alloc(value_buffer(i), GCHandleType.Pinned)
            value_array(i) = GC.AddrOfPinnedObject.ToInt32
        Next i
Tiger_Zhao你的办法可行~~~~ 最后我将 value_array()定义成Integer类型后,DLL 中的函数执行正常,但是没有返回值,有个问题,我发现使用以上代码将value_buffer() 中对应的内存地址赋到 value_array() 中,并执行了DLL中的函数后, value_buffer() 的内存地址会变化(我通过VS中带的监视器监视我传给 value_array()的内存地址可以看到正确的返回值),所以导致在value_buffer() 中还是看不到返回值,请问有什么办法在这个脚本执行过程中使 value_buffer() 的内存地址不发生变化呢??
tony198512 2016-01-14
  • 打赏
  • 举报
回复
我找到问题所在了,还需要大侠帮忙 一会我把问题写上来
Tiger_Zhao 2016-01-14
  • 打赏
  • 举报
回复
API函数被调用了和被正确调用了还差得远呢!
tony198512 2016-01-14
  • 打赏
  • 举报
回复
经过两天的测试现在不会提示错误了,但是没有返回值了,不过我感觉函数执行了
加载更多回复(36)
你想当“李逍遥”式的“大侠”吗? 这里无需计算机基础,无需编程经验,你也不必是计算机专业的在校大学生....只要爱好游戏,怀揣梦想! 有一定自主学习能力,跟着刘老师从“编程小白”修炼为游戏研发“大虾”吧!!!学习好Unity,其先决条件是一定要有稳固、扎实的编程基础!课程 《C# For Unity系列之入门篇》配套学习资料链接:http://pan.baidu.com/s/1gflxreN 密码:sou5;刘老师讲Unity学员群(2) 497429806一、热更新系列(技术含量:高级):A:《lua热更新技术级篇》https://edu.csdn.net/course/detail/27087B:《热更新框架设计之Xlua基础视频课程》https://edu.csdn.net/course/detail/27110C:《热更新框架设计之热更流程与热补丁技术》https://edu.csdn.net/course/detail/27118D:《热更新框架设计之客户端热更框架(上)》https://edu.csdn.net/course/detail/27132E:《热更新框架设计之客户端热更框架()》https://edu.csdn.net/course/detail/27135F:《热更新框架设计之客户端热更框架(下)》https://edu.csdn.net/course/detail/27136二:框架设计系列(技术含量:级): A:《游戏UI界面框架设计系列视频课程》https://edu.csdn.net/course/detail/27142B:《Unity客户端框架设计PureMVC篇视频课程(上)》https://edu.csdn.net/course/detail/27172C:《Unity客户端框架设计PureMVC篇视频课程(下)》https://edu.csdn.net/course/detail/27173D:《AssetBundle框架设计_框架篇视频课程》https://edu.csdn.net/course/detail/27169三、Unity脚本从入门到精通(技术含量:初级)A:《C# For Unity系列之入门篇》https://edu.csdn.net/course/detail/4560B:《C# For Unity系列之基础篇》https://edu.csdn.net/course/detail/4595C: 《C# For Unity系列之级篇》https://edu.csdn.net/course/detail/24422D:《C# For Unity系列之进阶篇》https://edu.csdn.net/course/detail/24465四、虚拟现实(VR)与增强现实(AR):(技术含量:初级)A:《虚拟现实之汽车仿真模拟系统 》https://edu.csdn.net/course/detail/26618五、Unity基础课程系列(技术含量:初级) A:《台球游戏与FlappyBirds—Unity快速入门系列视频课程(第1部)》 https://edu.csdn.net/course/detail/24643B:《太空射击与移动端发布技术-Unity快速入门系列视频课程(第2部)》https://edu.csdn.net/course/detail/24645 C:《Unity ECS(二) 小试牛刀》https://edu.csdn.net/course/detail/27096六、Unity ARPG课程(技术含量:初级):A:《MMOARPG地下守护神_单机版实战视频课程(上部)》https://edu.csdn.net/course/detail/24965B:《MMOARPG地下守护神_单机版实战视频课程(部)》https://edu.csdn.net/course/detail/24968C:《MMOARPG地下守护神_单机版实战视频课程(下部)》https://edu.csdn.net/course/detail/24979

1,486

社区成员

发帖
与我相关
我的任务
社区描述
VB API
社区管理员
  • API
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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