SDK's Unmanaged DLL in VB.NET (Pointer issues)

  • Thread starter Thread starter agitlin
  • Start date Start date
A

agitlin

Hello All,

I'm working with a SDK for a piece of hardware attached to a Windows
CE device. The sample code provided is all written in eVC++ and I'm
trying to port it over to a VB.NET application we're writing. Up to
this point I've been able to translate the code into VB.NET, but one
function (BK_EXTRACT) from the SDK has me perplexed.

In the interest of disclosure, I've barely got my head wrapped around
pointers. I'm sure what I'm doing isn't rocket science, but I could
still use a hand.

Here is the function's description in the developer's manual:
---
BK_API char *CaptureSensor(void)
Abstract: capture fingerprint image
Parameter: none
Remarks: this function is included in .dll
Return: return pointer to internal image buffer


BK_API int BK_EXTRACT(HANDLE Handle, BYTE* PixelsBuffer, BYTE
*Template, int PurposeMode)
Abstract: EXTRACT the characteristic template of fingerprint image in
current buffer, whose result put into the buffer pointed by Template.
Parameter:
Handle$B!'(B the algorithms handle returned by calling BK_API HANDLE
FPInit to initialize the fingerprint algorithms library
BYTE* PixelsBuffer$B!'(BA pointer to fingerprint image which will be
extracted later
BYTE *Template is used for buffering the extracted characteristic
template, the size should be configured at 2K in advance.
int PurposeMode$B!'(Bthe following parameters should be set up as below:
EXTRACT_FOR_ENROLLMENT (= 0)
EXTRACT_FOR_IDENTIFICATION (= 1)
EXTRACT_FOR_VERIFICATION (= 2)
Remarks: this function is included in the .dll
Return: return the real size of the fingerprint template if extracted
successfully, otherwise return <=0
---

Here's how it is used in eVC++:
---
int tmpLen=0;
BYTE tmp[2048];
int score=0,tid=0;
int tmpCapture=IsCapturing;
int ret;
if(tmpCapture)
{
pchImgBuf = CaptureSensor ();
if(pchImgBuf)
else
{
printf("Capture failed\n");
return 0;
}
IsCapturing=0;
}
else
return 0;
ret=FPTest(fhdl);
if(ret)
{
tmpLen=BK_EXTRACT(fhdl, (BYTE*)pchImgBuf,
tmp,EXTRACT_FOR_IDENTIFICATION);
}
---

Here is how I'm declaring those functions in VB.NET:
---
Declare Function CaptureSensor Lib "\Storage Card\Finger.DLL" ()
As IntPtr

Declare Function BK_EXTRACT Lib "\Storage Card\Finger.DLL" _
(ByVal FPInitHandle As IntPtr, _
ByRef PixelsBuffer As IntPtr, _
ByRef Template As Byte, _
ByVal PurposeMode As Integer) As Integer
---

And here's the code I have written thus far:
---
Dim ptrImageBuffer As IntPtr
Dim tmpLen As Integer
Dim bytPixelsBuffer(2048) As Byte
Dim bytTemplate(2048) As Byte

'On the interval, capture what the reader sees
Try
ptrImageBuffer = CaptureSensor()
Catch ex As Exception
End Try

'If we caught something, check it out
If (ptrImageBuffer) Then
'If it's an actual print on the reader, continue
If FPTest(fpcHandle) Then
'Extract the captured image as a template and an image
Try
tmpLen = BK_EXTRACT(fpcHandle, ptrImageBuffer,
bytTemplate(0), EXTRACT_FOR_IDENTIFICATION)
Catch ex As Exception
lblUSBStatus.Text = "Bioprint extraction failed: "
& ex.Message
End Try
End If
End If
End If
---

I've tried several things to get this to work, but I think I'm just
not sure how to properly use them. It would seem that I need to use
Marshall.Copy somewhere, but again, I'm just not getting my head
wrapped around it. I either throw CE native access violations or
stack overflows depending on what I try.

If anyone has any ideas or could lead me in the right direction I
would greatly appreciate it.

Thank you all in advance,
 
Hello All,

I'm working with a SDK for a piece of hardware attached to a Windows
CE device. The sample code provided is all written in eVC++ and I'm
trying to port it over to a VB.NET application we're writing. Up to
this point I've been able to translate the code into VB.NET, but one
function (BK_EXTRACT) from the SDK has me perplexed.

In the interest of disclosure, I've barely got my head wrapped around
pointers. I'm sure what I'm doing isn't rocket science, but I could
still use a hand.

Here is the function's description in the developer's manual:
---
BK_API char *CaptureSensor(void)
Abstract: capture fingerprint image
Parameter: none
Remarks: this function is included in .dll
Return: return pointer to internal image buffer


BK_API int BK_EXTRACT(HANDLE Handle, BYTE* PixelsBuffer, BYTE
*Template, int PurposeMode)
Abstract: EXTRACT the characteristic template of fingerprint image in
current buffer, whose result put into the buffer pointed by Template.
Parameter:
Handle$B!'(B the algorithms handle returned by calling BK_API HANDLE
FPInit to initialize the fingerprint algorithms library
BYTE* PixelsBuffer$B!'(BA pointer to fingerprint image which will be
extracted later
BYTE *Template is used for buffering the extracted characteristic
template, the size should be configured at 2K in advance.
int PurposeMode$B!'(Bthe following parameters should be set up as below:
EXTRACT_FOR_ENROLLMENT (= 0)
EXTRACT_FOR_IDENTIFICATION (= 1)
EXTRACT_FOR_VERIFICATION (= 2)
Remarks: this function is included in the .dll
Return: return the real size of the fingerprint template if extracted
successfully, otherwise return <=0
---

Here's how it is used in eVC++:
---
int tmpLen=0;
BYTE tmp[2048];
int score=0,tid=0;
int tmpCapture=IsCapturing;
int ret;
if(tmpCapture)
{
pchImgBuf = CaptureSensor ();
if(pchImgBuf)
else
{
printf("Capture failed\n");
return 0;
}
IsCapturing=0;
}
else
return 0;
ret=FPTest(fhdl);
if(ret)
{
tmpLen=BK_EXTRACT(fhdl, (BYTE*)pchImgBuf,
tmp,EXTRACT_FOR_IDENTIFICATION);
}
---

Here is how I'm declaring those functions in VB.NET:
---
Declare Function CaptureSensor Lib "\Storage Card\Finger.DLL" ()
As IntPtr

Declare Function BK_EXTRACT Lib "\Storage Card\Finger.DLL" _
(ByVal FPInitHandle As IntPtr, _
ByRef PixelsBuffer As IntPtr, _
ByRef Template As Byte, _
ByVal PurposeMode As Integer) As Integer
---

And here's the code I have written thus far:
---
Dim ptrImageBuffer As IntPtr
Dim tmpLen As Integer
Dim bytPixelsBuffer(2048) As Byte
Dim bytTemplate(2048) As Byte

'On the interval, capture what the reader sees
Try
ptrImageBuffer = CaptureSensor()
Catch ex As Exception
End Try

'If we caught something, check it out
If (ptrImageBuffer) Then
'If it's an actual print on the reader, continue
If FPTest(fpcHandle) Then
'Extract the captured image as a template and an image
Try
tmpLen = BK_EXTRACT(fpcHandle, ptrImageBuffer,
bytTemplate(0), EXTRACT_FOR_IDENTIFICATION)
Catch ex As Exception
lblUSBStatus.Text = "Bioprint extraction failed: "
& ex.Message
End Try
End If
End If
End If
---

I've tried several things to get this to work, but I think I'm just
not sure how to properly use them. It would seem that I need to use
Marshall.Copy somewhere, but again, I'm just not getting my head
wrapped around it. I either throw CE native access violations or
stack overflows depending on what I try.

If anyone has any ideas or could lead me in the right direction I
would greatly appreciate it.

Thank you all in advance,

For translating some of the API calls use the following tool (free from MS).

P/Invoke Interop Assistant

Search in MS and you can paste declaration code in and have it translated
correctly to VB/C#

LS
 
Hi LS,

That was incredibly helpful! I wish I had that last week when I
started this mess.

I'm running into a new issue now: I'm throwing an OverflowException
now. Here's my declaration:
<System.Runtime.InteropServices.DllImportAttribute("\Storage Card
\Finger.DLL", EntryPoint:="BK_EXTRACT")> _
Public Shared Function BK_EXTRACT(ByVal Handle As System.IntPtr,
ByRef PixelsBuffer As Byte, ByRef Template As Byte(), ByVal
PurposeMode As Integer) As Integer
End Function

And here's how I'm calling it:
---
Dim ptrImageBuffer As IntPtr
Dim tmpLen As Integer
Dim bytTemplate(2047) As Byte
Dim ptrTemplate

'On the interval, capture what the reader sees
Try
ptrImageBuffer = CaptureSensor
Catch ex As Exception
End Try

'If we caught something, check it out
If (ptrImageBuffer) Then
'If it's an actual print on the reader, continue
If FPTest(fpcHandle) Then
'Extract the captured image as a template and an image
Try
ptrTemplate = Marshal.AllocHGlobal(2048)
Marshal.Copy(ptrTemplate, bytTemplate, 0, 2047)

tmpLen = BK_EXTRACT(fpcHandle, ptrImageBuffer,
bytTemplate, EXTRACT_FOR_IDENTIFICATION)
Catch ex As Exception
lblUSBStatus.Text = "Bioprint extraction failed: "
& ex.Message
End Try

End If
End If
---

I feel like it has something to do with how I'm handling that byte
array... I just haven't been able to get it working.

Anyone with an idea?

Thanks again!
 
Thanks for the input Bill! Unfortunately that yielded the same result
- overflowexception.

The P/Invoke Interop Assistant named those as ByRef and in previous
research I found that should be the way to go. If I'm understanding
the scenario correctly, since we're making reference to the byte via a
pointer and not actually using the byte itself we need to set those
values as ByRef.

Regardless, thanks for chiming in!
 
Thanks for the input Bill! Unfortunately that yielded the same result
- overflowexception.

The P/Invoke Interop Assistant named those as ByRef and in previous
research I found that should be the way to go. If I'm understanding
the scenario correctly, since we're making reference to the byte via a
pointer and not actually using the byte itself we need to set those
values as ByRef.

Regardless, thanks for chiming in!

It's very very rare for arrays to be ByRef. Usually you want them ByVal and
apply the appropaite marshalling attributes including In, Out and either
LPArray or SafeArray. In this case LPArray. ByRef for an array variable is a
pointer to the array, not the first element.. a Pointer to the first
element would be ByRef element(0).

If I go back to your original code, I would try it as :

Declare Function BK_EXTRACT Lib "\Storage Card\Finger.DLL" _
(ByVal FPInitHandle As IntPtr, _
ByVal PixelsBuffer As IntPtr, _
<[In](), Out()> ByVal Template() As Byte, _
ByVal PurposeMode As Integer) As Integer
---

---
Dim ptrImageBuffer As IntPtr
Dim tmpLen As Integer
Dim bytPixelsBuffer(0 to 2047) As Byte
Dim bytTemplate(0 to 2047) As Byte

'On the interval, capture what the reader sees
Try
ptrImageBuffer = CaptureSensor()
Catch ex As Exception
' don't swallow exceptions
Throw
End Try

'If we caught something, check it out
If ptrImageBuffer <> IntPtr.Zero Then
'If it's an actual print on the reader, continue
If FPTest(fpcHandle) Then
'Extract the captured image as a template and an image
Try
tmpLen = BK_EXTRACT(fpcHandle, ptrImageBuffer,
bytTemplate, EXTRACT_FOR_IDENTIFICATION)
' need to deal with the need to make the array larger
here, and also if tmpLen is < 0

Catch ex As Exception
lblUSBStatus.Text = "Bioprint extraction failed: "
& ex.Message
End Try
End If
End If
End If
 
Thanks again Bill!

Unfortunately I'm still running into issues.

As soon as I declare PixelsBuffer as an IntPtr in the function
declaration, I get a native error from the device 0xC00000FD. That is
a stack overflow I believe. I've moved around the marshaling
attributes from what you suggested to other orientations and I receive
the same error. I get an overflow exception thrown from my
application if PixelsBuffer is a byte.

Again, thank you for the input, but this thing is still kickin' my
butt!
 
Thanks again Bill!

Unfortunately I'm still running into issues.

As soon as I declare PixelsBuffer as an IntPtr in the function
declaration, I get a native error from the device 0xC00000FD. That is
a stack overflow I believe.

Really hard to say. It maybe that you are getting the IntPtr wrong.

Oh, and if you are developing on a x64 machine and the dll is only 32 bit,
you might want to set your output to x86 only. Other than that, I'd be
looking at how you are getting that IntPtr.
 
Back
Top