vb.net 调用VC写的DLL 回调函数返回时提示错误:试图写入受保护的内存

时间:2022-04-09 14:03:08

Imports System.Runtime.InteropServices
Imports System.Reflection
Imports System.Threading

Public Class Form1
    '----------------------------------------------变量
    Dim user_id As UInt32
    Public HeartbeatThread As Thread = Nothing
    Public AIC As ALARM_INFO_CALLBACK = Nothing
    '-----------------------------------------------结构
    Public Structure msg_download_pic_t
        Public channel_no As Integer
        Public pic_len As UInt32
    End Structure
    Public Structure Plate_result
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=16)> _
        Public plate_num As String
        Public plate_rect As rect_s
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=28)> _
        Public plate_char_rec As Integer
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=7)> _
        Public plate_char_confid As Single
        Public confidence As Single
        Public plate_intensity As Integer
        Public plate_color As Integer
        Private plate_type As Integer
        Public vehicle_color As Integer
        Public TimeValue As UInt32
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=31)> _
        Public res As Integer
    End Structure
    Public Structure rect_s
        Public left_x As Integer
        Public left_y As Integer
        Public right_x As Integer
        Public right_y As Integer
    End Structure
    Public Structure msg_alarm_infoEx_t
        Public alarm_ack As Integer
        Public tm As msg_time_t
        Public alarm_id As Int32
        Public alarm_channel As Int32
        Public alarm_type As Int32
        Public ip As String
        Public alarm_info As String
        Public data As Byte
    End Structure
    Public Structure msg_time_t
        Public year As Integer
        Public month As Integer
        Public day As Integer
        Public hour As Integer
        Public minute As Integer
        Public second As Integer
    End Structure

    Public Structure plasta
        Public nState As Integer
        Public resver As String
    End Structure

    Public Structure audioTalk_config_t
        <MarshalAs(UnmanagedType.I4)> _
        Public iRate As Integer
        <MarshalAs(UnmanagedType.I4)> _
        Public iWidth As Integer
        <MarshalAs(UnmanagedType.I4)> _
        Public iFormat As Integer
        <MarshalAs(UnmanagedType.I4)> _
        Public iAmr_mode As Integer
        <MarshalAs(UnmanagedType.I4)> _
        Public iAmr_format As Integer
    End Structure


    '-----------------------------------------------委托
    Public Delegate Function ALARM_INFO_CALLBACK(ByVal msg_alarm_info As msg_alarm_infoEx_t, ByVal context As IntPtr) As Integer

    '----------------------------------------------引入dll

    ' =============================================初始化网络库
    <DllImport("decNetLib.dll", CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function st_net_initClientNetLib() As UInt32

    End Function

    '  ==========================================用户登录
    <DllImport("decNetLib.dll", CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function st_net_userLogin(ByVal user_id As UInt32) As Integer
    End Function

    '  ===========================================注册告警信息回调函数
    <DllImport("decNetLib.dll", CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function st_net_registerServerAlarmInfoCallback(ByVal user_id As UInt32, ByVal callback As ALARM_INFO_CALLBACK, ByVal context As IntPtr) As Integer

    End Function

    '  ===============================================获取心跳状态信息
    <DllImport("decNetLib.dll", CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function st_net_getHeartbeatStatus(ByVal user_id As UInt32) As Integer

    End Function

    '   ============================================初始网络服务信息

    <DllImport("decNetLib.dll", CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function st_net_initServerInfo(ByVal ip_addr As String, ByVal port As Integer, ByVal user_name As String, ByVal user_pwd As String) As UInt32
    End Function

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Control.CheckForIllegalCrossThreadCalls = False


    End Sub

 Private Shared Function callbak(ByVal msg_alarm_info As msg_alarm_infoEx_t, ByVal context As IntPtr) As Integer
        '当抓取车牌后 直接提示“试图写入受保护的内存”
    End Function

    Private Sub HeartbeatThreadStatus()

        Dim keepalive As Boolean = True

        While keepalive

            If user_id <> 0 Then

                ListBox1.Items.Add("心跳探测结果:" & st_net_getHeartbeatStatus(user_id))

            End If

            For t As Integer = 0 To 99
                If user_id <> 0 Then
                    ListBox1.Items.Add("心跳探测结果:" & st_net_getHeartbeatStatus(user_id))
                    st_net_registerServerAlarmInfoCallback(user_id, AIC, IntPtr.Zero)
                    Thread.Sleep(3000)

                Else
                    keepalive = False
                    Return
                End If
            Next
        End While

    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        ListBox1.Items.Add("初始网络:" & st_net_initClientNetLib())
        Dim ip As String = "192.168.1.110"
        Dim port As Integer = 9660
        Dim user As String = "Admin"
        Dim pass As String = "111111"
        user_id = st_net_initServerInfo(ip, port, user, pass)
        ListBox1.Items.Add("初始服务:" & user_id)
        ListBox1.Items.Add("用户登录:" & st_net_userLogin(user_id))

        HeartbeatThread = New Thread(New ThreadStart(AddressOf HeartbeatThreadStatus))
        HeartbeatThread.Start()

        AIC = New ALARM_INFO_CALLBACK(AddressOf callbak)
        GC.KeepAlive(AIC)

        ListBox1.Items.Add("注册回调函数:" & st_net_registerServerAlarmInfoCallback(user_id, AIC, IntPtr.Zero))
    End Sub
End Class



分不够可以现金,求大牛指导... 熬夜两晚上了 QQ:31560565

13 个解决方案

#1


问题一:既然用了回调函数,应该是一次注册后多次回调,你怎么 st_net_registerServerAlarmInfoCallback 注册了 100 次?
问题二:HeartbeatThreadStatus 开个线程出于什么考虑?看得莫名其妙。
问题三:有注册就应该有注销,st_net_unregisterServerAlarmInfoCallback 在哪里?

请先用 VC 做个样例,正常实现了回调功能,再用 VB.Net 模仿。

#2


VC 是有的  上面的代码也没写完.,可以帮忙转一下么?价格好商量


void CPlateDemoDlg::OnBnClickedButtonLogin()
{
UpdateData(TRUE);
st_net_initClientNetLib();
CString strIP;
m_ipAddr.GetWindowText(strIP);
m_lUserID = st_net_initServerInfo((LPSTR)(LPCTSTR)strIP,m_port,(LPSTR)(LPCTSTR)m_user,(LPSTR)(LPCTSTR)m_psw);

int iret = st_net_userLogin(m_lUserID);// 登录设备成功返回0
if(iret != 0)
{
st_net_deinitServerInfo(m_lUserID);
m_lUserID = 0;
        GetDlgItem(IDC_STATIC_INFO)->SetWindowText("登陆失败!");
return;
}

//开启心跳线程
m_iMsgThreadFlag = 1;
m_handle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)HeartbeatStatus,(LPVOID)this,0,0);

//注册告警回调,用于车牌信息上告
//void mhwnd = (void *)this
st_net_registerServerAlarmInfoCallback(m_lUserID,alarm_call_back,(void *)this);

m_bLogin = TRUE;
GetDlgItem(IDC_STATIC_INFO)->SetWindowText("登陆成功!");
}

DWORD WINAPI CPlateDemoDlg::HeartbeatStatus(LPVOID lpParam)
{
CPlateDemoDlg *pThis = (CPlateDemoDlg *)lpParam;
int iDeadCount = 0;
int iRet = 0;
while (pThis->m_iMsgThreadFlag)
{

iRet = st_net_getHeartbeatStatus(pThis->m_lUserID);
if (iRet == 1)
{
if (iDeadCount > 0)
{
TRACE("############  1.心跳周期复位 num = %d 。。。。。。。。\n", iDeadCount);
}

iDeadCount = 0;
}
else
{
iDeadCount++;
if (iDeadCount < 3)
{
for (int m = 0 ; m < 100 ;m ++)
{
if (pThis->m_iMsgThreadFlag == 0)
{
return 0;
}
Sleep(30);
}
continue;
}

if (pThis->m_bLogin == FALSE)
{
int nRet = st_net_userLogin(pThis->m_lUserID);
if(nRet != 0)
{
for (int m = 0 ; m < 30 ;m ++)
{
if (pThis->m_iMsgThreadFlag == 0)
{
return 0;
}
Sleep(30);
}
continue;
}

pThis->m_bLogin = TRUE;
st_net_registerServerAlarmInfoCallback(pThis->m_lUserID,alarm_call_back,(void *)pThis);
}
else
{
if (pThis->m_lUserID == 0)
{
return 0;
}
st_net_registerServerAlarmInfoCallback(pThis->m_lUserID,NULL,NULL);
st_net_userLogout(pThis->m_lUserID);
pThis->m_bLogin = FALSE;
}
}

for (int m = 0 ; m < 100 ;m ++)
{
if (pThis->m_iMsgThreadFlag == 0)
{
return 0;
}
Sleep(30);
}

}

return 0;
}

#3


爱莫能助啊,不会VB

#4


你应该VC dll的原型发出来

#5


引用 4 楼 Chinajiyong 的回复:
你应该VC dll的原型发出来


恩 的确VC开发的原型

#6


引用 1 楼 Tiger_Zhao 的回复:
问题一:既然用了回调函数,应该是一次注册后多次回调,你怎么 st_net_registerServerAlarmInfoCallback 注册了 100 次?
问题二:HeartbeatThreadStatus 开个线程出于什么考虑?看得莫名其妙。
问题三:有注册就应该有注销,st_net_unregisterServerAlarmInfoCallback 在哪里?

请先用 VC 做个样例,正常实现了回调功能,再用 VB.Net 模仿。


大牛  需要VC源码么? 我可以发给你

#7


引用 5 楼 zenter 的回复:
Quote: 引用 4 楼 Chinajiyong 的回复:

你应该VC dll的原型发出来


恩 的确VC开发的原型

主要是对vb不熟悉,给个思路去检查
首先保证VC的方法转换成VB正确(比如参数类型这些),转换没错的话(你目前转换的可以正常一个个调用成功么?和vc对照一下),然后自己去看看VC的源码的流程,照做调用(函数顺序)

#8


引用 7 楼 Chinajiyong 的回复:
Quote: 引用 5 楼 zenter 的回复:

Quote: 引用 4 楼 Chinajiyong 的回复:

你应该VC dll的原型发出来


恩 的确VC开发的原型

主要是对vb不熟悉,给个思路去检查
首先保证VC的方法转换成VB正确(比如参数类型这些),转换没错的话(你目前转换的可以正常一个个调用成功么?和vc对照一下),然后自己去看看VC的源码的流程,照做调用(函数顺序)

昨天调了一夜,每一步的返回结果也都对的 初始化就返回0  登录就返回用户id  错误密码会返回不同参数与说明文件也一致,就是回调返回就内存读写错误。。伤脑筋..

#9


请先用 VC 做个样例
请先用 VC 做个样例
请先用 VC 做个样例
没样例就不能证明dll是无错的。

#10


vc demo 有的 可以正常工作 代码太长 不让发  有Q没 发你一份

#11


你应该把.h文件贴出来。并不是所有c++的DLL都可以转为.net为平台直接用的。

#12


引用 11 楼 zanfeng 的回复:
你应该把.h文件贴出来。并不是所有c++的DLL都可以转为.net为平台直接用的。


恩 转换过程异常艰苦..感谢热心答复

#13


问题已解决,感谢大家的帮助! 在声明结构的过程中 与正常的声明有点不太一样 ,进过改正已可以正常工作了

#1


问题一:既然用了回调函数,应该是一次注册后多次回调,你怎么 st_net_registerServerAlarmInfoCallback 注册了 100 次?
问题二:HeartbeatThreadStatus 开个线程出于什么考虑?看得莫名其妙。
问题三:有注册就应该有注销,st_net_unregisterServerAlarmInfoCallback 在哪里?

请先用 VC 做个样例,正常实现了回调功能,再用 VB.Net 模仿。

#2


VC 是有的  上面的代码也没写完.,可以帮忙转一下么?价格好商量


void CPlateDemoDlg::OnBnClickedButtonLogin()
{
UpdateData(TRUE);
st_net_initClientNetLib();
CString strIP;
m_ipAddr.GetWindowText(strIP);
m_lUserID = st_net_initServerInfo((LPSTR)(LPCTSTR)strIP,m_port,(LPSTR)(LPCTSTR)m_user,(LPSTR)(LPCTSTR)m_psw);

int iret = st_net_userLogin(m_lUserID);// 登录设备成功返回0
if(iret != 0)
{
st_net_deinitServerInfo(m_lUserID);
m_lUserID = 0;
        GetDlgItem(IDC_STATIC_INFO)->SetWindowText("登陆失败!");
return;
}

//开启心跳线程
m_iMsgThreadFlag = 1;
m_handle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)HeartbeatStatus,(LPVOID)this,0,0);

//注册告警回调,用于车牌信息上告
//void mhwnd = (void *)this
st_net_registerServerAlarmInfoCallback(m_lUserID,alarm_call_back,(void *)this);

m_bLogin = TRUE;
GetDlgItem(IDC_STATIC_INFO)->SetWindowText("登陆成功!");
}

DWORD WINAPI CPlateDemoDlg::HeartbeatStatus(LPVOID lpParam)
{
CPlateDemoDlg *pThis = (CPlateDemoDlg *)lpParam;
int iDeadCount = 0;
int iRet = 0;
while (pThis->m_iMsgThreadFlag)
{

iRet = st_net_getHeartbeatStatus(pThis->m_lUserID);
if (iRet == 1)
{
if (iDeadCount > 0)
{
TRACE("############  1.心跳周期复位 num = %d 。。。。。。。。\n", iDeadCount);
}

iDeadCount = 0;
}
else
{
iDeadCount++;
if (iDeadCount < 3)
{
for (int m = 0 ; m < 100 ;m ++)
{
if (pThis->m_iMsgThreadFlag == 0)
{
return 0;
}
Sleep(30);
}
continue;
}

if (pThis->m_bLogin == FALSE)
{
int nRet = st_net_userLogin(pThis->m_lUserID);
if(nRet != 0)
{
for (int m = 0 ; m < 30 ;m ++)
{
if (pThis->m_iMsgThreadFlag == 0)
{
return 0;
}
Sleep(30);
}
continue;
}

pThis->m_bLogin = TRUE;
st_net_registerServerAlarmInfoCallback(pThis->m_lUserID,alarm_call_back,(void *)pThis);
}
else
{
if (pThis->m_lUserID == 0)
{
return 0;
}
st_net_registerServerAlarmInfoCallback(pThis->m_lUserID,NULL,NULL);
st_net_userLogout(pThis->m_lUserID);
pThis->m_bLogin = FALSE;
}
}

for (int m = 0 ; m < 100 ;m ++)
{
if (pThis->m_iMsgThreadFlag == 0)
{
return 0;
}
Sleep(30);
}

}

return 0;
}

#3


爱莫能助啊,不会VB

#4


你应该VC dll的原型发出来

#5


引用 4 楼 Chinajiyong 的回复:
你应该VC dll的原型发出来


恩 的确VC开发的原型

#6


引用 1 楼 Tiger_Zhao 的回复:
问题一:既然用了回调函数,应该是一次注册后多次回调,你怎么 st_net_registerServerAlarmInfoCallback 注册了 100 次?
问题二:HeartbeatThreadStatus 开个线程出于什么考虑?看得莫名其妙。
问题三:有注册就应该有注销,st_net_unregisterServerAlarmInfoCallback 在哪里?

请先用 VC 做个样例,正常实现了回调功能,再用 VB.Net 模仿。


大牛  需要VC源码么? 我可以发给你

#7


引用 5 楼 zenter 的回复:
Quote: 引用 4 楼 Chinajiyong 的回复:

你应该VC dll的原型发出来


恩 的确VC开发的原型

主要是对vb不熟悉,给个思路去检查
首先保证VC的方法转换成VB正确(比如参数类型这些),转换没错的话(你目前转换的可以正常一个个调用成功么?和vc对照一下),然后自己去看看VC的源码的流程,照做调用(函数顺序)

#8


引用 7 楼 Chinajiyong 的回复:
Quote: 引用 5 楼 zenter 的回复:

Quote: 引用 4 楼 Chinajiyong 的回复:

你应该VC dll的原型发出来


恩 的确VC开发的原型

主要是对vb不熟悉,给个思路去检查
首先保证VC的方法转换成VB正确(比如参数类型这些),转换没错的话(你目前转换的可以正常一个个调用成功么?和vc对照一下),然后自己去看看VC的源码的流程,照做调用(函数顺序)

昨天调了一夜,每一步的返回结果也都对的 初始化就返回0  登录就返回用户id  错误密码会返回不同参数与说明文件也一致,就是回调返回就内存读写错误。。伤脑筋..

#9


请先用 VC 做个样例
请先用 VC 做个样例
请先用 VC 做个样例
没样例就不能证明dll是无错的。

#10


vc demo 有的 可以正常工作 代码太长 不让发  有Q没 发你一份

#11


你应该把.h文件贴出来。并不是所有c++的DLL都可以转为.net为平台直接用的。

#12


引用 11 楼 zanfeng 的回复:
你应该把.h文件贴出来。并不是所有c++的DLL都可以转为.net为平台直接用的。


恩 转换过程异常艰苦..感谢热心答复

#13


问题已解决,感谢大家的帮助! 在声明结构的过程中 与正常的声明有点不太一样 ,进过改正已可以正常工作了