Callback problem

  • Thread starter Trisax via DotNetMonster.com
  • Start date
T

Trisax via DotNetMonster.com

Hi

I want to import this function in my VB.Net program

Original C++ Function:
SetFilter(WORD pid,void* lpFunc, DWORD CallBackType, DWORD size, DWORD *lpfilter_num)
this function generates the follow Callback:
void __stdcall YourCallBack(BYTE *Buff, int lenBuff)


My code:

Public Delegate Function myCallBack(ByVal Buffer As String, ByVal size As Integer) As Boolean

<DllImport("mydll", EntryPoint:="SetFilter", _
SetLastError:=True, CharSet:=CharSet.Unicode, _
ExactSpelling:=True, _
CallingConvention:=CallingConvention.StdCall)> _
Public Shared Function SetFilter(ByVal pid As Integer, ByVal lpFunc As myCallBack, ByVal CallBackType As Integer, ByVal size As Integer, ByVal lpfilter_num As Long) As Boolean
End Function

The function works but the Buffer retrieved from MyCallBack is incorrect and the lenght doesn't match to it

I have tried also to insert this structure:

<StructLayout(LayoutKind.Sequential)> _
Public Structure MyPoint
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=2)> Public buff() As Byte
'Public x As String
End Structure 'MyPoint

but after few seconds crashes :( maybe i have to use a GCHandle but I do't know how
 
M

Mattias Sjögren

Public Delegate Function myCallBack(ByVal Buffer As String, ByVal size As Integer) As Boolean

This should be a Sub (no return type) to match the C++ declaration.
You may also want to consider changing the Buffer parameter type to an
IntPtr and manually copy the data to the form you want it.

<DllImport("mydll", EntryPoint:="SetFilter", _
SetLastError:=True, CharSet:=CharSet.Unicode, _
ExactSpelling:=True, _
CallingConvention:=CallingConvention.StdCall)> _
Public Shared Function SetFilter(ByVal pid As Integer, ByVal lpFunc As myCallBack, ByVal CallBackType As Integer, ByVal size As Integer, ByVal lpfilter_num As Long) As Boolean

This should be

Public Shared Function SetFilter(ByVal pid As Short, ByVal lpFunc As
myCallBack, ByVal CallBackType As Integer, ByVal size As Integer,
ByRef lpfilter_num As Integer) As ???

(??? since the C++ declaration you posted doesn't include the return
type)



Mattias
 
T

Trisax via DotNetMonster.com

Thanks for your reply

The return type of the C++ declaration is BOOL:

BUFF_API BOOL SetFilter(WORD pid,void* lpFunc, DWORD CallBackType, DWORD size, DWORD *lpfilter_num);

If true the callback will called

void __stdcall YourCallBack(BYTE *Buff, int lenBuff)
You may also want to consider changing the Buffer parameter type to an
IntPtr and manually copy the data to the form you want it.<

I have tried also with
Public Delegate Sub myCallBack(ByRef Buffer As IntPtr, ByVal lLen As Integer)

but when I use Marshal.ReadByte(Buffer, 0) I catch an error

Note:
The buffer lenght retrieved by lenBuff is always 188
and ALL the bytes passed in 1 Second are about 80KB!!!

if I use my first Callback:
Public Delegate Sub myCallBack(ByVal Buffer As String, ByVal lLen As Integer)

Everything works, only the string is wrong

Else if I use a structure the follow structure also works

<StructLayout(LayoutKind.Sequential)> _
Public Structure MyPoint
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=2)> Public buff() As Byte
'Public x As String
End Structure 'MyPoint

but the SizeConst is only 2, if change to 188 after few callbacks it crashes


Thank you again for your reply
I hope you can help me
Trisax
 
T

Trisax via DotNetMonster.com

Thank you again but I'm gone crazy!!!
This is the code, please help me!

Imports System.Runtime.InteropServices

Public Class DLLCLS

<DllImport("DLL", EntryPoint:="SetFilter", _
SetLastError:=True, CharSet:=CharSet.Unicode, _
ExactSpelling:=True, _
CallingConvention:=CallingConvention.StdCall)> _
Public Shared Function SetFilter(ByVal pid As Integer, ByVal lpFunc As MAIN.myCallBack, ByVal CallBackType As Integer, ByVal size As Integer, ByVal lpfilter_num As Long) As Boolean
End Function

'Original C++
'API BOOL SetFilter(WORD pid,void* lpFunc, DWORD CallBackType,
DWORD size, DWORD *lpfilter_num);

End Class

Public Class MAIN

Public Delegate Sub myCallBack(ByVal buff As String, ByVal lLen As Integer)

'Original C++ Callback
'void __stdcall YourCallBack(BYTE *Buff, int lenBuff)

Dim DLLCB As DLLCLS
Dim Address As myCallBack 'Without this then callback crashes

Sub Main()
Address = AddressOf CallBack
If DLLCB.SetFilter(210, Address, 2, 1, 0) = True Then
'lpFunc will be called on data arrival
End If
End Sub

Public Sub CallBack(ByVal buff As String, ByVal lLen As Integer)
'Here I'd view the buffer of data with lenght=lLen
End Sub

End Class
 
M

Mattias Sjögren

<DllImport("DLL", EntryPoint:="SetFilter", _
SetLastError:=True, CharSet:=CharSet.Unicode, _
ExactSpelling:=True, _
CallingConvention:=CallingConvention.StdCall)> _
Public Shared Function SetFilter(ByVal pid As Integer, ByVal lpFunc As MAIN.myCallBack, ByVal CallBackType As Integer, ByVal size As Integer, ByVal lpfilter_num As Long) As Boolean

You haven't made the changes here I suggested in my first reply (make
pid a Short and lpfilter-num ByRef As Integer).



Mattias
 
T

Trisax via DotNetMonster.com

I Solved it!
The problem was't in DLLIMPORT but, for a banal error, in the Delegate.

As you wrote
You may also want to consider changing the Buffer parameter type to an
IntPtr and manually copy the data to the form you want it.

so this is the right :
Public Delegate Sub myCallBack(ByVal Buffer As IntPtr, ByVal lLen As Integer)

Now I can use "marshal.readbyte"

Many thanks for your help
Trisax
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top