Groups | Blog | Home
all groups > dotnet interop > january 2007 >

dotnet interop : Need a method to send byte arrays from Unmanaged C DLL to VB.Net



Vince Castellano
1/12/2007 3:55:55 PM
Hello,
I posted this to m.p.d.languages.vb, but was told this is a better
place to ask (and I worded my question poorly there, so I think I
miss-communicated my question).

What I need to do is send a parameter from VB.net to an Unmanaged C dll
call, and that parameter on the C side is a pointer to unsigned char,
and is assumed to be allocated n bytes (which is also a parameter).
VB.net needs to be able to send an empty Byte() that will be filled by
the DLL. I have access to both the C and the VB.net, so can make
changes in all the appropriate places.

I have attempted to do with with a memcpy and byte by byte with pointer
arithmetic, but I get a stack overflow, or an unbalanced stack message.
Here are some relevant code snippets trying to express what it is I am
attempting:

Unmanaged C DLL code:

int _stdcall getBytes(unsigned char* vbBytes, int alloced, int* filled)
{
int i;
// Hard code for testing
unsigned char cBytes[] = {
0x03, 0x84, 0x44, 0xc1, 0x12, 0x61, 0xb5, 0x4A, 0x21, 0x00,
0xe0, 0x7f, 0xff, 0x00, 0xcb, 0xa9, 0x33, 0x34, 0x7f, 0x4A,
0x01, 0x7f, 0xff, 0x00, 0xca, 0x8f, 0x55, 0x7f, 0x39, 0x1c,
0x4c, 0x23, 0x00, 0xcd, 0x00, 0xaf, 0xc3, 0xc8, 0x00, 0x30,
0x0c, 0x50, 0x00, 0x10, 0x58, 0x03, 0xff, 0x00, 0x01, 0x30,
0x03, 0xdc, 0xe4, 0x9f, 0x4b, 0xd2, 0x66, 0x04, 0x64, 0xc2,
0x1f, 0x00 };

if(alloced < 62)
return 1;

/* This won't work either
for(i = 0; i < alloced; i++)
*(vbBytes++) = *(cBytes++);
*filled = i;
*/
memcpy(vbBytes, cBytes, alloced);
*filled = alloced;

return 0;
}

VB.net:
Private Declare Auto Function getBytes Lib "example.dll" _
(ByRef bytes As Byte(), ByVal alloced As Integer, ByVal
filled As Integer) As Integer

Public Sub getState()
Dim ba(75) As Byte
Dim filled As Integer
getBytes(ba, 74, filled)
For Each b As Byte In ba
Debug.Print(String.Format("0x{0:x2}", b))
Next
End Sub
Mattias Sjögren
1/13/2007 10:17:43 AM
Vince,

[quoted text, click to view]

I thought it was pretty clear the first time. And my answer is still
that you need to pass the Byte aray ByVal.


Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Vince Castellano
1/15/2007 9:27:43 AM
[quoted text, click to view]

I tried this, and got a 'System.AccessViolationException'. Therefore, I
had assumed that you thought I meant sending data from the VB.net
application to the DLL, where what I wanted was just to send an array
from VB.net to the C DLL to be filled, and then used by VB.net.

What would be the correct way on the DLL side to fill this array when
passed ByVal, as memcpy does not seem to work still.

Thank you for your help,
Vince
Vince Castellano
1/15/2007 1:46:59 PM
Mattias,

[quoted text, click to view]

Sorry for the double post, but I looked into the URL
(http://www.dotnetinterop.com) in your signature, and I found
information that worked for me there.

Turned out if I sent it ByVal an IntPtr, and then used the Marshal
functions to allocate and pull bytes out, it worked fine. I was unaware
of the Marshal class, so I did not do this before. Now I just redim my
Byte() the size filled (usually but not always equal to alloced), and
pull out the bytes using Marshal.ReadByte(pCurrent) one by one.

Thank you again for your time, and I hope that if any one else has this
issue, this post will have enough info to help.

Vince Castellano
Mattias Sjögren
1/16/2007 7:39:37 AM
Vince,

[quoted text, click to view]

Probably due to a bug in your C code, not a marshaling failure.

for(i = 0; i < alloced; i++)

should be

for(i = 0; i < 62; i++)


Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
AddThis Social Bookmark Button