|
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;
ptr=(int *)malloc(sizeof(int));
*ptr=10;
printf("The address of ptr is %d and its values is %d\n",ptr,*ptr);
free(ptr);
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: dim ptr as long
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: 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: Dim hHeap As Long hHeap = GetProcessHeap()
ptr=HeapAlloc(hHeap,0,2)
We can even check if memory was allocated. if ptr<>0 then
end if
Now, *ptr=10;
In Visual Basic we'll use the function CopyMemory which is declared like so: 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.
Public Declare Sub CopyMemoryWrite Lib "kernel32" Alias _
"RtlMoveMemory" (Byval Destination As long, Source As Any, _
ByVal Length As Long)
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. dim i as integer
i=10
CopyMemoryWrite ptr,i,2
Now towards line 5.
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 HeapFree GetProcessHeap(),0,ptr
Here is the complete listing of the source code: (just copy it into a project and run it). 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
Dim hHeap As Long
hHeap = GetProcessHeap()
ptr = HeapAlloc(hHeap, 0, 2)
If ptr <> 0 Then
Dim i As Integer
i = 10
CopyMemoryWrite ptr, i, 2
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) 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
pNext As Long
End Type
Private Sub CreateLinkedList()
Dim pFirst As Long, pSecond As Long
Dim hHeap As Long
hHeap = GetProcessHeap()
pFirst = HeapAlloc(hHeap, 0, 504)
pSecond = HeapAlloc(hHeap, 0, 504)
If pFirst <> 0 And pSecond <> 0 Then
PutDataIntoStructure pFirst, "Hello", pSecond
PutDataIntoStructure pSecond, "Pointers", 0
pHead = pFirst
End If
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
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 49 (Total in Forum: 49) (Refresh) | FirstPrevNext |
|
 |
|
|
I have one question: why?
VB was written to avoid such stuff. If you need to allocate vectors, there are easier ways of doing it with a couple of API calls; otherwise, all we're doing here is creating our own heap in which to store data. VB (and most other languages) do this without the coder having to deal with pointers. Isn't it easier to say:
Dim Arry() as Long Redim Arry(Num) Arry(Num-1)=10 Debug.Print Arry(Num-1)
I don't need a pointer, CopyMemory, etc. If I want a faster routine using CopyMemory, I can always use AddressOf or something similar.
What am I missing?
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
Yes, same question for me.
(VBA) The only thing I see is that the redim doesn't work inside a sub() when the array is passed as a parameter to the sub. So the array has to be dimmed public. And the management of the redimming and preserving of data works only for the last dimension in a multi dimensional arry.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi,
Can any one tell me how to execute a .exe file from resource without extracting it to a file.
I have created a .dll file with one of .exe file saved as resource. or may be i will create a single file with multiple files combined together and i want to load a .exe file from that single file without extracting to a separate .exe file and executing it.
I know how a .wav file can be executed directly from a .dll without extracting it and saving it as a .wav file
Thanks in advance Bye!
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
|
Thanks for the code, but the above example is too complex for the newibles. I found some ideas from the MSDN help. In VB, the most easiest way to dynamic allocation is using ReDim command. The following is the sample code:
Private Type mytype i As Integer k As String * 200 End Type
Private z() As mytype
Private Sub cmdAllocate_Click() ReDim z(1000) End Sub
Private Sub cmdFreeUp_Click() Erase z End Sub Also, there is another way to getting the variable pointer by the VarPtr() function, StrPtr() and ObjPtr are for the strings and objects respectively.
Hope these can help someone.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
That will work until a subsequent redim moves the array data to a new starting memory location. At that point, your program will crash and burn - all the pointers you have stored become invalid. You will have to use the array indeces, not the memory pointers.
That is a different topic, and a different algorithm. Franceso Balena has a great example at http://www.devx.com/vb2themax/Tip/19308.
Sure there are some ptr functions in vb. And even more are hidden away - http://support.microsoft.com/kb/199824/EN-US/ shows how to define VarPtrAray. But you'll still need copymemory or its equivalent to use them. Once once you do that, you can often recast parameters, just as the author has done here, and use implicit pointers, in which case you don't always need the overhead of the explicit ptr functions.
BTW - Of course this is too complex for nubes, this is dealing with pointers...but without articles like this, you'll need a good foundation in something like c or asm or even fortran to tackle pointers in vb
d00d
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Hi all,
What I have to do is as follows: 1) There are two processes: A.exe and B.exe 2) A.exe allocates a memory block of bytes (131 bytes) using HealAlloc WinAPI. 3) A.exe sends it to B.exe using SendMessage/WM_COPYDATA. 4) B.exe receive, processes and finally deallocates it using HeapFree WinAPI.
That's right! A.exe allocates, but B.exe deallocates it.
I've coded as follows, but failed to get what I wanted. Please someone help me on this.
1) A.exe declares a local Byte array variable (Total_PL) to store the data to send to B.exe, and fills it with some information.
Dim TOTAL_PL(0 To 130) As Byte Dim Sbj As String * 32 Dim Series As String * 15 Dim DateTime As String * 16
Sbj = "This is a subject" Series = "TOTAL_PL" DateTime = Format(Now, "YYYYMMDD00HHMMSS")
CopyMemory(Total_PL(0), 131, 4) ' first 4 bytes will have the total length of data => 131 CopyMemory(Total_PL(4), 5, 1) ' second 1 byte will have data type => 5 Call CopyMemory(Total_PL(5), 0, 2) ' 0 Call CopyMemory(Total_PL(7), 0, 4) ' 0 Call CopyMemory(Total_PL(11), 0, 2) ' 0 Call CopyMemory(Total_PL(13), 0, 4) ' 0 Call CopyMemory(Total_PL(17), 0, 2) ' 0 Call CopyMemory(Total_PL(19), 0, 1) ' 0 Call CopyMemory(Total_PL(20), 0, 4) ' 0 Call CopyMemory(Total_PL(24), 0, 4) ' 0 Call CopyMemory(Total_PL(28), 67, 2) ' actual Data lenght => 67 Call CopyMemory(Total_PL(30), &HFFFE, 2) ' &HFFFE Call CopyMemory(Total_PL(32), ByVal Sbj, Len(Sbj)) ' "This is a subject" Call FillMemory(Total_PL(64), 2, Asc(" ")) ' two blanks Call CopyMemory(Total_PL(66), ByVal Series, Len(Series)) ' "TOTAL_PL" Call CopyMemory(Total_PL(81), htonl(0), 4) ' Call CopyMemory(Total_PL(85), ByVal "01", Len("01")) ' "01" Call CopyMemory(Total_PL(87), htonl(&HF1F2F3F4), 4) ' &HF1F2F3F4 in network byte order Call CopyMemory(Total_PL(91), htonl(&HE1E2E3E4), 4) ' &HE1E2E3E4 in network byte order Call CopyMemory(Total_PL(95), htonl(0), 4) ' 0 Call CopyMemory(Total_PL(99), htonl(0), 4) ' 0 Call CopyMemory(Total_PL(103), htonl(0), 4) ' 0 Call CopyMemory(Total_PL(107), CDbl(0), 8) ' 0.0 as Double Call CopyMemory(Total_PL(115), ByVal DateTime, Len(DateTime)) ' Date and Time
2) Now, A.exe allocates a memory block from heap using HeapAlloc.
Dim pTotal_PL As Long
pTotal_PL = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS Or HEAP_ZERO_MEMORY, 131) If pTotal_PL = 0 Then Debug.Print "memory allocation failed!" Exit Sub End If
3) CopyMemory Total_PL into pTotal_PL.
Call CopyMemory(pTotal_PL, VarPtr(Total_PL(0)), 131)
The reason why I do like in 1) through 3) is because I don't know how to do it directly using pTotal_PL alone. If you know, just let me know how please.
4) Fill COPYDATASTRUCT and SendMessage/WM_COPYDATA to B.exe.
Dim cds As COPYDATASTRUCT With cds .dwData = 2 ' Don't worry about this value. It has meaning only to me. .cbData = 131 ' size of data to be sent .lpData = pTotal_PL ' VarPtr(Total_PL(0)) End With
Dim nSbId As Long Dim WinWnd As Long
nSbId = &HFFFE WinWnd = FindWindow(vbNullString, "B.exe")
Call SendMessage(WinWnd, WM_COPYDATA, nSbId, cds)
5) B.exe receives 131 bytes from A.exe, processes it as it wishes, and finally deallocates it using HeapFree somehow.
6) For your reference, please see http://www.thescarms.com/vbasic/PassString.asp[^].
I've tried everything I could, but failed yet. Please someone write A.exe and B.exe source code for me. I really appreciate it.
LHR
-- modified at 17:30 Monday 7th August, 2006
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I was wrong about the usage of SendMessage. Memory sent via SendMessage should NOT be freed from another process.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Sorry, you cannot do that. In 32-bits OS, 2 processes cannot share the same heap space (each application has unique data into they memory space)
Solutions for sharing memory is "File Mapping" functions like CreateFileMapping() and OpenFileMapping()
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Hi, I am new on VB. Maybe this is very simple problem but I don't know. I have a class as ;
Public Class Form1 Inherits System.Windows.Forms.Form Friend WithEvents MainMenu1 As System.Windows.Forms.MainMenu .... .... Public Const ERROR_SUCCESS = 0 Public Const REG_OPTION_NON_VOLATILE = 0 Public Const REG_SZ = 1 Public Const HKEY_LOCAL_MACHINE As Long = &H80000002 Declare Function RegOpenKeyEx Lib "Coredll" Alias "RegOpenKeyExW" (ByVal hKey As Long, _ ByVal lpSubKey As String, _ ByVal ulOptions As Long, _ ByVal samDesired As Long, _ ByVal phkResult As Long) As Long
.... ....
As you see above there is a dll called "Coredll". And I don't know where to put Option Explicit. When I put that before ;
.... .... Option Explicit Declare Function RegOpenKeyEx Lib "Coredll" ..... .... .... there is error. Do you help me?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Hi Stefan and All CodeProject(ers) I am writing code that reads frames from a video and manipulates them on a pixel(byte) level
I tried the code but I am getting a memory leak. The HeapFree command doesn't appear to uanallocate the memory. Monitoring the 'Windows Task Manager' 'Page File Usage' Each time I run the code about 5MB is added (the size of my HD image 1920x1080) It only reduces when I exit the program, so if am am running a big file, the memory runs out.
Dim byteptr_out As Long Dim hHeap As Long
hHeap = GetProcessHeap() byteptr_out = HeapAlloc(hHeap, 0, (((ImageX * 3) + 3) And &HFFFC) * ImageY)
HeapFree GetProcessHeap(), 0, byteptr_out
|
| Sign In·View Thread·PermaLink | 2.00/5 (2 votes) |
|
|
|
 |
|
|
I have an image heap block in the browser's local machine. I get this by executing a scanner interface ActiveX API from the browser's vbscript. For this image, I can get the pointer and the bytecount of the block. So all I want is to copy to my local variable hence I can play with it, like send to server, show in browser etc
I found similar articles, in the web
Look for below snippet in below url...
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" _ Alias "RtlMoveMemory" (Destination As Any, _ Source As Any, ByVal Length As Long)
http://www.codeproject.com/vbscript/how_to_do_pointers_in_visual_basic.asp http://www.codeproject.com/useritems/UB_Pointers_In_VB.asp?print=true
And I want to do something like this in my HMTL vbscript code....
<SCRIPT LANGUAGE="VBScript"> <!-- Private Declare Sub CopyMemory Lib "kernel32" _ Alias "RtlMoveMemory" (Destination As Any, _ Source As Any, ByVal Length As Long)
Sub cpMemory CopyMemory Destination, FrontBWImageAddress, FrontBWImageByteCount MsgBox(Destination) End Sub --> </SCRIPT>
But I get syntax/runtime errors... thanks in advance.
thanks and Cheers!! )m
)m
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
'Hi: I say, thank you for the next help, 'I have this code: 'I have declare 3 callback functions: Public Declare Function PAC_ADT_SET_FINGER_STATUS Lib "D:\_basic_bio\ADT_spi.dll" ( _ ByVal FingerStatus As Integer, _ ByRef Image As Long, _ ByVal RowNumber As Long, _ ByVal ColumnNumber As Long, _ ByRef ContinueFlag As Long) As Integer
Public Declare Function PAC_ADT_SET_MESSAGE Lib "D:\_basic_bio\ADT_spi.dll" ( _ ByVal MessageID As Integer, _ ByRef ContinueFlag As Long) As Integer Public Declare Function PAC_ADT_SET_ADT_STATUS Lib "D:\_basic_bio\ADT_spi.dll" ( _ ByVal StatusID As Byte, _ ByRef ContinueFlag As Long) As Integer
'I declare this structure The member are pointers to callback functions Type AC_ADT_GUI_CALLBACK AC_ADT_SetFingerStatus As Long AC_ADT_SetMessages As Long AC_ADT_SetADTStatus As Long End Type 'then I have declare a function from DLL that is the function register the callback routines, where your parameter is the address of the callback procedures. 'Before was ByRef GuiCallBackFunction As AC_ADT_GUI_CALLBACK but is wrong Public Declare Function AC_ADT_SetGUICallbacks Lib "D:\_basic_bio\ADT_spi.dll" ( _ ByRef GuiCallBackFunction As Long) As Integer
' I use this Trick for Address of pointers Public Function DeclareFunction(ByVal pointer As Long) As Long DeclareFunction = pointer End Function 'then I create 3 function for linking in a structure. Public Function FCB_PAC_ADT_SET_FINGER_STATUS() As Long FCB_PAC_ADT_SET_FINGER_STATUS = DeclareFunction(AddressOf PAC_ADT_SET_FINGER_STATUS) End Function Public Function FCB_PAC_ADT_SET_MESSAGE() As Long FCB_PAC_ADT_SET_FINGER_STATUS = DeclareFunction(AddressOf PAC_ADT_SET_MESSAGE) End Function Public Function FCB_PAC_ADT_SET_ADT_STATUS() As Long FBC_PAC_ADT_SET_ADT_STATUS = DeclareFunction(AddressOf PAC_ADT_SET_ADT_STATUS) End Function 'here the callback Sub main() Dim GuiCallBackFunction As AC_ADT_GUI_CALLBACK GuiCallBackFunction.AC_ADT_SetFingerStatus = DeclareFunction(AddressOf FCB_PAC_ADT_SET_FINGER_STATUS) GuiCallBackFunction.AC_ADT_SetMessages = DeclareFunction(AddressOf FCB_PAC_ADT_SET_MESSAGE) GuiCallBackFunction.AC_ADT_SetADTStatus = DeclareFunction(AddressOf FCB_PAC_ADT_SET_ADT_STATUS) 'here the error AC_ADT_SetGUICallbacks(GuiCallBackFunction)
End Sub
I understand that the problem is the type parameter argument that is passed, It must be : long (for address pointer, byref o byval? ) or using the name of the struct.
I need any help.
Thanks.
Joe Valenz
|
| Sign In·View Thread·PermaLink | 2.00/5 (2 votes) |
|
|
|
 |
|
|
Hi there,
Maybe this question is very basic but anyway. How do i dump the contents of the allocated area to a file?
I use a dll to do some work in text and it produces a result that is proportional to the size of the text passed. I dont know if it returned the right result so i was thinking about dumping the pointer contents to a file. My app goes like this: 'Allocating memory bufSize = Len(input) * 300000 resBuf = HeapAlloc(GetProcessHeap(), 0, bufSize) 'here i pass the text. resBuf is populated???
i = crypto_usebuffer(chHnd, text, resBuf, bufSize)
By the way i tried copymemory but it crashed
Best Regards, Robson
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
Hi, I want to take response form user where he press yes/no at serverside from client side <% msg = "Enter Choice" Response.Write("<" & "script language=VBScript>") Response.Write("MsgBox """ & msg & """,vbYesNo<" & "/script>") %> above code display me messagebox . but how can get response where he click Yes/No. if yes then i want to excute code in script Regards Sachin
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi, I want to take response form user where he press yes/no at serverside from client side <% msg = "Enter Choice" Response.Write("<" & "script language=VBScript>") Response.Write("MsgBox """ & msg & """,vbYesNo<" & "/script>") %> above code display me messagebox . but how can get response where he click Yes/No. if yes then i want to excute code in script Regards Sachin
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi Friends
I've a doubt in VB. If u guys know the solution please let me know.
Is there a way to have a name of a variable in a variable? Let me ask u with the help of an eg.:
x=500 y=200 z=600
a="y"
Now, the variable-a has the string value "y". Thru "a" I just want to print the value of the variable that "a" represents. In the above eg., the output should be 200.
Is there any way to do this in VB?
Bye Srik
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
Hello Srik, When u assigning a="y", There is no relation between variable y and Character "y", They are totally different by their definition.
If you want to write a alias to a variable u have to use pointer. U may use the following code,
int x=500,y=200,z=600,a,*ptr; ptr=&y; a=*ptr;
I wrote in C because I am a C Programmer. U can refer the same article where u wrote this question to convert to this code to VB.
Have A Nice Day Bye

|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi Friend, i'm not sure that my answer is correct or not.but i want to give u a suggesion about this question. (Try to take the variable Y as Pointer Type Variable) Eg: *y=200 (* means value at address) then assign it to (a) eg:- x=500 *y=200 z=600
a=*y (this gives the value 200) ------------------------------------------------------
By Rohit
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
|
I have the following lines of code ' Long variable MyBuffer contains the starting address ' of a buffer MyImage.SetSize 640, 480 MyImage.SetImagePointer MyBuffer
My question is
How can I access the address of a "buffer variable" and put that value into a variable MyBuffer?
Thanks
rfcapo
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
| | |