 |
eddom Level: Big Cheese
 Registered: 14-03-2006 Posts: 24
|
Anything wrong with my code?
Dim VersionNum As String
<DllImport("Vertx.dll")> Public Shared Function GetDLLVersion(ByRef VersionNum As String, ByVal DataSize As Integer) As Integer
End Function
GetDLLVersion(VersionNum, 10)
------------------------------------------------------------------------
note: the original structure of the GetDLLVersion is:
int GetDLLVersion(Char *data, int datasize)
data = array to caontain the DLL Version
datasize = size of data
So, the original structure should be a C language, thus i try to store the *data into the variable name VersionNum using the method of ByRef, is this wrong?
|
|
14-03-2006 at 09:06 AM |
|
|
Goran Level: Moderator
 Registered: 16-05-2002 Posts: 1681
|
Re: Anything wrong with my code?
I believe it should be the opposite to both parameters:
(Byval VersionNum As String, Byref DataSize As Integer
Why dont you use DllGetVersion which is OS built in function?
____________________________
If you find the answer helpful, please mark this topic as solved.
|
|
14-03-2006 at 04:56 PM |
|
|
eddom Level: Big Cheese
 Registered: 14-03-2006 Posts: 24
|
Re: Anything wrong with my code?
Why it should be opposite?? Not that "Char *data" going to update the variable name "data"?? The "VersionNum" will be update if we use byVal for "VersionNum"?? Actually i am testing out how to store the returned value from the function called, so i wish to know is there any reference that i can look for to solve this problem... since char *data is only one of it... i got another problem is where the function require a parameter of HWND type but VB.NET doesn't support that anymore.
|
|
15-03-2006 at 12:41 AM |
|
|
Goran Level: Moderator
 Registered: 16-05-2002 Posts: 1681
|
Re: Anything wrong with my code?
I dont understand the first question. VB and C manages strings differently. You dont store the value, you just pass the string to the API, and set the string to the lenght that can accept the size of the data... YOu can see the example of GetComputerName API, which works similary as I believe this API does. Again, I dont understand why are you using something that you dont know how it works, and if it works correctly, since you have MS API I posted above, that I believe does the same thing.
As for the HWND, in VB6 it is of Long type, in VB.NET it is of Integer type.
____________________________
If you find the answer helpful, please mark this topic as solved.
|
|
15-03-2006 at 03:55 PM |
|
|
eddom Level: Big Cheese
 Registered: 14-03-2006 Posts: 24
|
Re: Anything wrong with my code?
Ya, i know Microsoft API can done that, but i just wanna try to deal with the dll other than the window API, since there are still more function i need to call from that dll, so at this stage, i am trying to make myself familiar with controlling the API. So, what you mean of pass the string to the API?? and how can we set the string to the lenght that can accept the size of the data? that is what i really cant understand, i got read through many example done by other, what i saw is some of them use the IntPtr method to store the returned pointer and later on use the marshal.copy to copy the value to a valiable. some are just use the <marshalas(unmanagedtype....)> to done this. I actually blur with that already, which one should be used?? As the API doc i have for the dll file, it state that the version value will be returned after we call that function, so what i trying to do now is to retrieve that value. Could you guide me on this?
|
|
15-03-2006 at 06:26 PM |
|
|
Goran Level: Moderator
 Registered: 16-05-2002 Posts: 1681
|
Re: Anything wrong with my code?
Ok try this code, and see if it works. If there are errors, post the error message and the line that it causing it.
' module declaration
' change the DllName.dll to the actual dll's name
| Declare Function GetDLLVersion Lib "DllName.dll" (ByVal VersionNum As String, ByRef DataSize As Integer) As Integer |
' form code
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim VersionNumber As String
Dim RetVal As Integer
VersionNumber = Space(256)
RetVal = GetDLLVersion(VersionNumber, 256)
MessageBox.Show(VersionNumber.Substring(0, RetVal))
End Sub |
[Edited by Goran on 16-03-2006 at 01:48 AM GMT]
____________________________
If you find the answer helpful, please mark this topic as solved.
|
|
16-03-2006 at 12:41 AM |
|
|
eddom Level: Big Cheese
 Registered: 14-03-2006 Posts: 24
|
Re: Anything wrong with my code?
quote: Goran wrote:
Ok try this code, and see if it works. If there are errors, post the error message and the line that it causing it.
' module declaration
' change the DllName.dll to the actual dll's name
| Declare Function GetDLLVersion Lib "DllName.dll" (ByVal VersionNum As String, ByRef DataSize As Integer) As Integer |
' form code
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim VersionNumber As String
Dim RetVal As Integer
VersionNumber = Space(256)
RetVal = GetDLLVersion(VersionNumber, 256)
MessageBox.Show(VersionNumber.Substring(0, RetVal))
End Sub |
[Edited by Goran on 16-03-2006 at 01:48 AM GMT]
No error was produce by the code you provided, but it returned empty string. I cheked the porperties of that dll file, the version number is "2.2.3.0"
The first time when i deal with this problem, i tried the code below and it returned the first character only, which is "2" :
' module declaration
| Declare Function GetDLLVersion Lib "DllName.dll" (ByRef VersionNum As Char, ByRef DataSize As Integer) As Integer |
' form code
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim VersionNum As Char
RetVal = GetDLLVersion(VersionNum, 10)
MessageBox.Show(VersionNum)
End Sub |
There are something that i am comfused:
1) Char *data is a pointer in C right? it return the pointed address of the value izzit? Not suppose that we have to use ByRef? Since byRef was used in VB.NET to return the value changed to the caller.
2) Someone told me that we cant just store the string returned from C to the string type of variable in VB.Net, because VB.Net string != C Null Terminator String. Is that true?
thanks for the guidance.
[Edited by eddom on 16-03-2006 at 09:31 AM GMT]
|
|
16-03-2006 at 01:29 AM |
|
|
Goran Level: Moderator
 Registered: 16-05-2002 Posts: 1681
|
Re: Anything wrong with my code?
YOu need to create a buffer enough to hold a string. Try this:
Versionnum=space(10)
RetVal = GetDLLVersion(VersionNum, 10) |
just beware that if version has more than 10 chars, rest of it will be truncated.
____________________________
If you find the answer helpful, please mark this topic as solved.
|
|
16-03-2006 at 10:20 AM |
|
|
eddom Level: Big Cheese
 Registered: 14-03-2006 Posts: 24
|
Re: Anything wrong with my code?
So, is that the whole program should be like this?
Declare Function GetDLLVersion Lib "Vertx.dll" (ByRef VersionNum As IntPtr, ByVal DataSize As Integer) As Integer
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim VersionNumber As String
Dim RetVal As Integer
VersionNumber = Space(10)
RetVal = GetDLLVersion(VersionNumber, 10)
MessageBox.Show(VersionNumber.Substring(0, RetVal))
End Sub
|
But the VersionNumber still return empty string, what actually wrong with that??
|
|
16-03-2006 at 01:37 PM |
|
|
Goran Level: Moderator
 Registered: 16-05-2002 Posts: 1681
|
Re: Anything wrong with my code?
I assumed that this particual function as a result returns the number of characters that is stored in a buffer, like many similar Win32 API's do, but could be it isnt the case with this API. So, to be sure try without the SubString method, I believe it will work
MessageBox.Show(VersionNumber)
If it displays a version number, then you may check for DataSize parameter, which could contain the number of characters that are returned in VersionNum...
____________________________
If you find the answer helpful, please mark this topic as solved.
|
|
16-03-2006 at 08:03 PM |
|
|
Goran Level: Moderator
 Registered: 16-05-2002 Posts: 1681
|
Re: Anything wrong with my code?
It seems that your C declaration is not correct... The first advice I gave you was the correct one: string should be passed ByVal, not ByRef. If you have a char variable in C, in Vb it should be array of bytes, as I recall, but I thought it could be done by passing a BSTR stringByRef (the actual buffer), opposite to LPSTR string, which should be passed ByVal - which means you are passing pointer to a buffer.
Anyway, if you have send this dll earlier, we didnt have to go through all this troubles. 
Private Declare Function GetDLLVersion Lib "Vertx.dll" (ByVal VersionNum As String, ByRef DataSize As Integer) As Integer
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim VersionNumber As String
Dim BufferSize As Integer = 255
Dim RetVal As Integer
VersionNumber = Space(BufferSize)
RetVal = GetDLLVersion(VersionNumber, BufferSize)
VersionNumber = VersionNumber.Substring(0, VersionNumber.IndexOf(Chr(0)))
MessageBox.Show(VersionNumber)
End Sub |
[Edited by Goran on 17-03-2006 at 02:46 AM GMT]
____________________________
If you find the answer helpful, please mark this topic as solved.
|
|
17-03-2006 at 01:42 AM |
|
|
eddom Level: Big Cheese
 Registered: 14-03-2006 Posts: 24
|
Re: Anything wrong with my code?
woooo, Goran, you are genious!!!
I work with this everyday to figure out the solution but i still cant get, since like you need little time only to solve that!!!
But can i ask you some question which i really cant understand:
1) As i know, ByRef is used with the function to change the variable of the caller right?? Eg:
Function CalTotal(ByRef Total, ByVal A, ByVal B)
Total = A + B
End Function
Dim Total, A, B as integer
A=1
B=1
CalTotal(Total, A, B)
|
After the function called, Total will be 2 right??
But since like the structure of GetDLLVersion is:
| int GetDLLVersion (Char *data, Int datasize) |
not that it mean this function going to return the data throught *data?? then why we are using ByVal? Why not ByRef? since ByRef used to return the value.
other than that, why we used ByRef for the int datasize?? why not ByVal?? since we are passing data inside.
2)i remember that you said hWnd in VB = Handle in VB.NET, what actually is hWnd and Handle?? i did read some reference from net, it said that handle in VB.Net is an int32, what that mean?? is the integer pointed to the Handle??
i got another function which is:
| int Initialization(int port, HWND hWnd, HINSTANCE hInst) |
i understood the int port, but how we going to declare this function??Is this correct??
| Private Declare Function Initialization Lib "Vertx.dll" (ByVal Port As Integer, ByVal HWND as HandleRef, HINSTANCE as Int32) As Integer |
The API Doc explan that HINSTANCE = instance in program using DLL
What is instance a method??
Sorry for asking so many question, cox i am really new to all this kind of things. Thanks for helping me
[Edited by eddom on 17-03-2006 at 11:07 PM GMT]
|
|
17-03-2006 at 03:05 PM |
|
|
Goran Level: Moderator
 Registered: 16-05-2002 Posts: 1681
|
Re: Anything wrong with my code?
quote: then why we are using ByVal? Why not ByRef? since ByRef used to return the value.
Not correct when dealing with strings, it is a little different. API generally require fixed length strings.
If you pass a string by value, you will be passing pointer to a first byte of data in that string.
If you pass a string by reference, you will be passing a pointer to a pointer which refers to first byte of data in that string. A pointer is a memory address.
VB strings in general should be passed by value. When dll modifies data in a string, it is very important to previously allocate enough bytes in memory to hold the data. This is why we first set string to some length (usually 255 if we dont know the actual lenght of the data that will be written) - we allocate a buffer to receive data.
If for example, you allocate only 10 bytes for returned data (not counting the header - VB strings are of BSTR type, and consist of header and data), and the returned value needs 11 bytes, it will write the last byte on some other location in memory - which causes general fault protection error (GPF), and VB usually crashes.
quote: other than that, why we used ByRef for the int datasize?? why not ByVal?? since we are passing data inside.
now here we have a different story. With both ByVal and ByRef you will be passing data, only with ByVal you are passing a copy of data, and with ByRef you are passing the actual data. Both declarations in your example will have the same effect. But lets assume (as I did), that this dll returns the length of the returned data in datasize parameter.
VB6 example of GetComputerName API
Declare Function GetComputerName Lib "kernel32" Alias "GetComputerNameA" (ByVal lpBuffer As String, nSize As Long) As Long
Dim BufferSize As Long
Dim DataBuffer As String
BufferSize = 32 'this is the max lenght for computer name
DataBuffer = Space(BufferSize)
'Get the computer name
GetComputerName DataBuffer, BufferSize |
DataBuffer now contains the name of the computer, but it also contains spaces after the computer name (we have allocated 32 bytes for this string). BufferSize now contains the lenght of the computer name, for ex 8, so we use it in left function to truncate spaces
| DataBuffer = Left(DataBuffer, BufferSize) |
quote: 2)i remember that you said hWnd in VB = Handle in VB.NET, what actually is hWnd and Handle?? i did read some reference from net, it said that handle in VB.Net is an int32, what that mean?? is the integer pointed to the Handle??
Windows OS when reffering to a window (ex form), it reffers to its handle - hwnd. in VB.NET, integer = int32, and it is a data type. This means that handle of a window is of Integer data type in VB.NET (IN Vb6 it is of Long data type).
As for HINSTANCE type, never heard of it, but it should be the common Integer type in VB.NET (Long type in VB6).
I believe the declaration in Vb.NET should be:
| Private Declare Function Initialization Lib "Vertx.dll" (ByVal Port As Integer, ByVal HWND as integer, ByVal HINSTANCE as Integer) As Integer |
____________________________
If you find the answer helpful, please mark this topic as solved.
|
|
17-03-2006 at 09:18 PM |
|
|
eddom Level: Big Cheese
 Registered: 14-03-2006 Posts: 24
|
Re: Anything wrong with my code?
So, it will be the same case for the unsigned Char *data and structure type as well??
We just have to create a structure with enough size to store the record??
Ps: i got read some post from other ppl, they solve this kind of problem using the IntPtr, Marshal or StringBuilder. So, is there any different with the method we used here?? It seen like those method are quite troublesome, but did it provide other advantages?
|
|
18-03-2006 at 08:54 AM |
|
|
Goran Level: Moderator
 Registered: 16-05-2002 Posts: 1681
|
Re: Anything wrong with my code?
IF depends on a structure.... some of them needs a space to allocate, some dont.... MOst strucutures that need to have xxSize memeber, which will hold the number of bytes that need to be allocated to this strucutre.
I am still talking here how it is dealt with it in VB6, not VB.NET. I didnt have problems with API's when tried them in Vb.NET, so I am not aware of the other methods you are saying. If problems arise in the future, then I will search in that direction.
And I am not a C programmer, so I dont know how to do it will all types, I know only about those I have dealt with it, but once you understand how API works with parameters, it will be easier to make it to work.
____________________________
If you find the answer helpful, please mark this topic as solved.
|
|
18-03-2006 at 10:38 AM |
|
|
|
|
 |
 |