Click here to Skip to main content
15,914,447 members
Articles / Programming Languages / VBScript
Article

How to do pointers in Visual Basic

Rate me:
Please Sign up or sign in to vote.
4.83/5 (26 votes)
3 Sep 2000 489.3K   60   49
Show how to use pointers in a C like manner

Introduction

Most people think that Visual Basic does not have pointers and hence is not capable of handling data structures that require pointers (by the way these data structures can be implemented using classes).

Well, they are right but not for very long. Since Visual Basic has access to the entire Win32 API it is not so difficult to equip it with pointers. Let's look at a simple code fragment in C and then at its Visual Basic equivalent.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
    int * ptr;                        //1               
    ptr=(int *)malloc(sizeof(int));   //2             
    *ptr=10;                          //3             
    printf("The address of ptr is %d and its values is %d\n",ptr,*ptr); //4
    free(ptr);                        //5
    return 0;
}

I have marked the lines with numbers so you ,the reader, can follow more easily.

The equivalent of the first line, in VB is:

VBScript
dim ptr as long   'int * ptr; 

This was easy because it follows from the definition of the pointer. A pointer is just a variable whose value is the address of another variable. It is long because a pointer in MS Windows is 4 bytes.

The second line:

VBScript
ptr=(int *)malloc(sizeof(int)); 

Well, how do we allocate memory dynamically in Visual Basic? malloc has no equivalent. Here we'll use the Win32 API function HeapAlloc(...).Please check the documentation for more information on it.

So here's our code:

VBScript
Dim hHeap As Long hHeap = GetProcessHeap()
ptr=HeapAlloc(hHeap,0,2) 'an integer in Visual Basic is 2 bytes

We can even check if memory was allocated.

VBScript
if ptr<>0 then 
    'memory was allocated
    'do stuff
end if

Now,

*ptr=10;

In Visual Basic we'll use the function CopyMemory which is declared like so:

VB
Public Declare Sub CopyMemory Lib "kernel32" Alias _
    "RtlMoveMemory" (Destination As Any, Source As Any, _
    ByVal Length As Long)

Here's the little trick : I modify the parameters and have two more definitions.

VBScript
'to write to memory
Public Declare Sub CopyMemoryWrite Lib "kernel32" Alias _
    "RtlMoveMemory" (Byval Destination As long, Source As Any, _
    ByVal Length As Long)

' to read from memory
Public Declare Sub CopyMemoryRead Lib "kernel32" Alias _
    "RtlMoveMemory" (Destination As Any,byval Source As Long, _
    ByVal Length As Long)

Now here's how,

*ptr=10;

translates into Visual Basic.

VBScript
dim i as integer 
i=10
CopyMemoryWrite ptr,i,2 ' an intger is two bytes

Now towards line 5.

VBScript
'printf("%d\n",*ptr);
dim j as integer
CopyMemoryRead j,ptr,2
MsgBox "The adress of ptr is " & cstr(ptr) & _
    vbCrlf & "and the value is " & cstr(j)

Now free the memory

VBScript
HeapFree GetProcessHeap(),0,ptr

Here is the complete listing of the source code: (just copy it into a project and run it).

VBScript
Option Explicit

Private Declare Sub CopyMemory Lib "kernel32" _
    Alias "RtlMoveMemory" (Destination As Any, _
    Source As Any, ByVal Length As Long)
Private Declare Function GetProcessHeap Lib "kernel32" () As Long
Private Declare Function HeapAlloc Lib "kernel32" _
    (ByVal hHeap As Long, ByVal dwFlags As Long,_
     ByVal dwBytes As Long) As Long
Private Declare Function HeapFree Lib "kernel32" _
    (ByVal hHeap As Long, ByVal dwFlags As Long, lpMem As Any) As Long
Private Declare Sub CopyMemoryWrite Lib "kernel32" Alias _
    "RtlMoveMemory" (ByVal Destination As Long, _
    Source As Any, ByVal Length As Long)
Private Declare Sub CopyMemoryRead Lib "kernel32" Alias _
    "RtlMoveMemory" (Destination As Any, _
    ByVal Source As Long, ByVal Length As Long)

Private Sub Form_Load()
    Dim ptr As Long   'int * ptr;
    Dim hHeap As Long
    hHeap = GetProcessHeap()
    ptr = HeapAlloc(hHeap, 0, 2) 'an integer in Visual Basic is 2 bytes
    If ptr <> 0 Then
    'memory was allocated
    'do stuff
        Dim i As Integer
        i = 10
        CopyMemoryWrite ptr, i, 2 ' an intger is two bytes
        Dim j As Integer
        CopyMemoryRead j, ptr, 2
        MsgBox "The adress of ptr is " & CStr(ptr) & _
            vbCrLf & "and the value is " & CStr(j)
        HeapFree GetProcessHeap(), 0, ptr
    End If
End Sub

Bonus

Here is a simple and not complete implementation of a linked list. (On the form put a Command button named Command1)

VBScript
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory"_
    (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function GetProcessHeap Lib "kernel32" () As Long
Private Declare Function HeapAlloc Lib "kernel32" _
    (ByVal hHeap As Long, ByVal dwFlags As Long, _
    ByVal dwBytes As Long) As Long
Private Declare Function HeapFree Lib "kernel32" _ 
    (ByVal hHeap As Long, ByVal dwFlags As Long, _
    lpMem As Any) As Long
Private Declare Sub CopyMemoryPut Lib "kernel32" Alias _
    "RtlMoveMemory" (ByVal Destination As Long, _
    Source As Any, ByVal Length As Long)
Private Declare Sub CopyMemoryRead Lib "kernel32" Alias _
    "RtlMoveMemory" (Destination As Any, _
    ByVal Source As Long, ByVal Length As Long)

Dim pHead As Long
Private Type ListElement
    strData As String * 255 '==255 * 2=500 bytes  vbStrings are UNICODE !
    pNext As Long  '4 bytes
                'pointer to next ; ==0 if end of list
'----------------
'total: 504 bytes
End Type

Private Sub CreateLinkedList()
'add three items to list
' get the heap first
    Dim pFirst As Long, pSecond As Long 'local pointers
    Dim hHeap As Long
    hHeap = GetProcessHeap()
    'allocate memory for the first and second element
    pFirst = HeapAlloc(hHeap, 0, 504)
    pSecond = HeapAlloc(hHeap, 0, 504)
    If pFirst <> 0 And pSecond <> 0 Then
    'memory is allocated
        PutDataIntoStructure pFirst, "Hello", pSecond
        PutDataIntoStructure pSecond, "Pointers", 0
        pHead = pFirst
    End If
    'put he second element in the list
End Sub

Private Sub Command1_Click()
    CreateLinkedList
    ReadLinkedListDataAndFreeMemory
End Sub

Private Sub PutDataIntoStructure(ByVal ptr As Long, _
        szdata As String, ByVal ptrNext As Long)
Dim le As ListElement
    le.strData = szdata
    le.pNext = ptrNext
    CopyMemoryPut ptr, le, 504
End Sub

Private Sub ReadDataToStructure(ByVal ptr As Long, _ 
        struct As ListElement)
Dim le As ListElement
    CopyMemoryRead le, ptr, 504
    struct.strData = le.strData
    struct.pNext = le.pNext
End Sub

Private Sub ReadLinkedListDataAndFreeMemory()
Dim pLocal As Long
Dim hHeap As Long
Dim le As ListElement
Dim strData As String
    pLocal = pHead
    hHeap = GetProcessHeap()
    Do While pLocal <> 0
        ReadDataToStructure pLocal, le
        strData = strData & vbCrLf & le.strData
        HeapFree hHeap, 0, pLocal
        pLocal = le.pNext
    Loop
    MsgBox strData
End Sub

Private Sub Form_Load()

End Sub

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Bulgaria Bulgaria
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralRe: Name of a variable in a variable!!! Pin
rohitfredrick8-Sep-05 13:13
rohitfredrick8-Sep-05 13:13 
QuestionSize of a picture? Pin
Anonymous18-Nov-03 12:35
Anonymous18-Nov-03 12:35 
Questionwhat is pHead Pin
hesterloli12-Nov-03 16:08
hesterloli12-Nov-03 16:08 
Questionresolution by a pointer? Pin
rfcapo16-Aug-03 4:21
rfcapo16-Aug-03 4:21 
Generalsize of an object in vb Pin
Anonymous4-Apr-03 4:43
Anonymous4-Apr-03 4:43 
GeneralRe: size of an object in vb Pin
Daniel Turini4-Apr-03 5:04
Daniel Turini4-Apr-03 5:04 
GeneralRe: size of an object in vb Pin
Anonymous4-Jun-03 0:10
Anonymous4-Jun-03 0:10 
GeneralVisual Basic to C dll - pointers Pin
Rick Bell8-Feb-03 8:48
Rick Bell8-Feb-03 8:48 
This is something that I am currently struggling with it my code.

I have dll that was written in C that I have to communicate to the API interface.
I have read a number of articles on this subject but yet I still don't feel I have everything right because app is still crashing after calling to the interface.

First issue, I had to do was make sure the dll was being built as stdcall as oppose to _cdecl to make sure they were being read of the stack correctly when I transition from VB to the dll.

Second issue, was using ByVal instead of ByRef on the string pointers.

Third issue was making sure the memory has been allocated for the string. I will put sample code.

Your article was very interesting to me, one of the better ones I had read. This transition from VB to a C dll is much more difficult than people think.

Here is a sample of my code that I have questions on:

This is the header definition of a sample C Function that I am calling in the dll.

extern "C" RadioAte_api int fixtureInitialize(int fixtureId, char *configDirectory,
int *adapterId, int *fixCmdStatus);

This is declaration of the call in VB.
I am not real clear on when to use ByVal vs. ByRef for the private function and public function declared below. Can you clear this up?
I also notice that you were using “as” instead of “As”.
I had not seen this in any other article except yours.
What is the difference between the lower case “as” vs. the upper case “As”?
This was defined in a class clsT3ATE

Private Declare Function fixtureInitialize Lib "stdradioate.dll" Alias "#10" ( _
ByVal iFixtureId As Integer, ByVal pConfigDirectory As String, _
pAdapterId As Integer, pFixCmdStatus As Integer) As Integer

This is a wrapper around the above function

Public Function InitializeFixture(ByVal iFixtureId As Integer, _
pConfigDirectory As String, pAdapterId As Integer, _
pFixCmdStatus As Integer) As Integer
Dim rv As Long

rv = fixtureInitialize(iFixtureId, pConfigDirectory, pAdapterId, pFixCmdStatus)

InitializeFixture = rv
End Function

I define the class
Public oT3ATE As clsT3ATE
Public Const constFixtureId = 1 ‘ Global constant

I noticed that you used a lower case “as” when you want a pointer and I am not.
Is this a problem?
Dim strConfigDirectory As String ‘ This should be char* pointer
Dim iAdapterId As Integer ‘ This should be int* pointer
Dim iFixCmdStatus As Integer ‘ This should be int* pointer
Dim iRV As Integer ‘ This should be int

I noticed on all values are pointers you were doing an allocation of the memory with the heap allocation.
Do I need to do this for the string and int pointers?

strConfigDirectory = Space(12)
iAdapterId = 1
iFixCmdStatus = 0
rv = 0

rv = oT3ATE.InitializeFixture(constFixtureId, strConfigDirectory, iAdapterId, _
iFixCmdStatus)

Finally, is there any application like Boundschecker developed by the NuMega to check for memory leaks and over writes for C dll in that would check VB code.?

Generalfirst sub gives a error Pin
Job523-Dec-02 0:32
Job523-Dec-02 0:32 
GeneralPls let me know the solution ASAP..reg. Printer Automation Pin
21-Oct-02 21:29
suss21-Oct-02 21:29 
GeneralGreat tut!! Pin
Anonymous17-Sep-02 11:22
Anonymous17-Sep-02 11:22 
GeneralFreed Pin
ColinDavies30-Aug-02 0:01
ColinDavies30-Aug-02 0:01 
GeneralOne more thing Pin
6-Apr-02 4:21
suss6-Apr-02 4:21 
GeneralDude about Mathematical calc in example Pin
2-Apr-02 3:56
suss2-Apr-02 3:56 
Generalcopy objects Pin
ankalu24-Jan-02 7:10
ankalu24-Jan-02 7:10 
GeneralVery Slick Pin
paris15-Nov-01 17:54
paris15-Nov-01 17:54 
GeneralPretty Cool Pin
Nish Nishant4-Nov-01 0:17
sitebuilderNish Nishant4-Nov-01 0:17 
GeneralStefan - You're missing the point Pin
Klaus Probst3-Feb-01 11:17
Klaus Probst3-Feb-01 11:17 
GeneralRe: Stefan - You're missing the point Pin
ManOfFire6-May-04 22:32
ManOfFire6-May-04 22:32 
GeneralEnlighten me, please Pin
10-Nov-00 0:28
suss10-Nov-00 0:28 
GeneralRe: Enlighten me, please Pin
Amans13-Jan-03 22:26
Amans13-Jan-03 22:26 
GeneralHow to call f( [in, out] BSTR* pstr) in VBScript? Pin
Maggiem23-Jan-03 9:23
Maggiem23-Jan-03 9:23 
GeneralDûh.... Pin
Dexter5-Sep-00 0:08
Dexter5-Sep-00 0:08 
GeneralPointers in VB Pin
Alex4-Sep-00 12:54
Alex4-Sep-00 12:54 
GeneralRe: Pointers in VB Pin
29-Mar-01 22:37
suss29-Mar-01 22:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.