Announcement
Collapse
No announcement yet.
Very unusual problem.
Collapse
X
-
Thank you Sir Hutchesson, I learn much from here. Also Thank you to Everyone here.
-
If you have a strong enough stomach, here is how to use the CALL DWORD notation to call a function in a DLL dynamically. The help file is about as clear as mud.
Code:' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ #include "\basic\include\win32api.inc" ' ------------------------------------- ' Make a prototype for the DLL function ' ------------------------------------- DECLARE FUNCTION MyMBox LIB "tim.dll" ALIAS "MyMsgbox" _ (BYVAL hWnd AS DWORD,lpText AS ASCIIZ, _ lpCaption AS ASCIIZ,BYVAL dwType AS DWORD) AS LONG ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ FUNCTION PBmain as LONG LOCAL rval as DWORD LOCAL hLib as DWORD LOCAL MyMsgBox as DWORD hLib = LoadLibrary("tim.dll") MyMsgbox = GetProcAddress(hLib,"MyMsgbox") ' |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| CALL DWORD MyMsgBox USING MyMBox(0,"How D","Title",%MB_OK) TO rval ' |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| FreeLibrary hLib End FUNCTION ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
Leave a comment:
-
Something I did not take enough notice of with the comments for Tim was how you have to call a dynamically linked DLL (the reason why they are called DYNAMIC link libraries). PB does not have a tidy way of calling functions from a DLL dynamically and you are stuck with CALL DWORD notation which is really clunky to code. I personally do DLL calls of this type in assembler as its far faster to code and a lot easier to read but its not a common technique for folks who code in high level basic.
If anyone is interested, here is how I would do it.
Code:' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ ' compile with pbwin10 ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ #compile exe "call2.exe" #option largemem32 #include "\basic\include\win32api.inc" MACRO FUNCTION rvcall4(procedure,arg1,arg2,arg3,arg4) MACROTEMP rval LOCAL rval as DWORD ! push arg4 ! push arg3 ! push arg2 ! push arg1 ! call procedure ! mov rval, eax END MACRO = rval MACRO FUNCTION localstr(quoted_text,bytecount) MACROTEMP szstring LOCAL szstring as STRINGZ * bytecount szstring = quoted_text END MACRO = VarPtr(szstring) ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ FUNCTION PBmain as LONG LOCAL hLib as DWORD LOCAL MyMsgbox as DWORD LOCAL rval as DWORD LOCAL ptxt as DWORD LOCAL pttl as DWORD hLib = LoadLibrary("tim.dll") MyMsgbox = GetProcAddress(hLib,"MyMsgbox") ptxt = localstr("How D Awl",64) pttl = localstr("Title",64) ' ||||||||||||||||||||||||||||||||||||||||||| rval = rvcall4(MyMsgbox,0,ptxt,pttl,%MB_OK) ' ||||||||||||||||||||||||||||||||||||||||||| rval = FreeLibrary(hLib) End FUNCTION ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
Code:' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ ' compile with pbwin10 ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ #COMPILE DLL GLOBAL DLLinstance as DWORD ' the DLLs instance handle #INCLUDE "\basic\include\win32api.inc" ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ FUNCTION LibMain(BYVAL hInst as LONG, _ BYVAL Reason as LONG, _ BYVAL Reserved as LONG) as LONG LOCAL RetVal as DWORD Select Case Reason Case %DLL_PROCESS_ATTACH DLLinstance = hInst ' make DLL instance global RetVal = 1 ' needed so DLL will start End Select FUNCTION = RetVal END FUNCTION ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ FUNCTION MyMsgbox ALIAS "MyMsgbox"( ByVal hwnd as DWORD, _ ptxt as ASCIIZ, _ titl as ASCIIZ, _ ByVal styl as DWORD _ ) EXPORT as LONG MessageBox hwnd,ptxt,titl,styl FUNCTION = 0 END FUNCTION ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
Leave a comment:
-
To answer your question, FreeLibrary() releases any memory used by the DLL.
Leave a comment:
-
Are there additional memory clearance statements kinda similar to RESET and ERASE which we can use so that variables used in the DLLs are cleared
when we exit these DLLs ?
And unless you have done some fairly unusual things, any variables used by procedures in your DLL are not visible in your main program, so resetting or clearing hardly seems necessary. They really cannot be using "that much" memory.. and if they are you should probably be explicity resetting them in your using procedures prior to exiting those procedures.
All that said, there are certain calls which produce system objects (e.g GLOBAL string variables , GDI objects created by LoadImage() and the like, COM objects (NEWCOM, ANYCOM) , some others) and unless explicitly reset or closed will remain part of your process, consuming memory until the process ends, at which time the Windows operating system will deallocate them. .
Leave a comment:
-
Tim,
Yes if you split up the resources into separate DLLs and load them on demand. It means using LoadLibrary(), GetProcAddress() and FreeLibrary() but it is a really efficient way to handle large amounts of data rather than just allocating very large amounts of memory in a single application. The allocation is done by the EXE you create but you get nothing for nothing, it just does it for you.
To answer your question, FreeLibrary() releases any memory used by the DLL.
Leave a comment:
-
Originally posted by Tim Lakinir View PostThank you Everyone
One more question related to Steve's response
Does this means that instead of executing one big program, you can have one main program MainProg.exe calling several DLLs
say child1.dll , child2.dll and child3.dll each of which would load a portion of the original big program into memory.
Doing this way, it would be more efiicient in terms of memory allocation than having to execute one big program ?
The question is that :
If we have called say child2.dll and then close it and then go back to the MainProg.exe , will the memory of child2.dll
still persist after we have close up child2.dll ?
Are there additional memory clearance statements kinda similar to RESET and ERASE which we can use so that variables used in the DLLs are cleared
when we exit these DLLs ?
In normal circumstances when explicit linking is used, DLL's stay linked to the process it was executed with, in this case MainProg.exe. The only benefit DLLs have is maintainability if patches need to be distributed only DLLs need to be downloaded if the main executable is kept as small as possible and another use-case is re-using functions for other executables. Download a program called Dependency Walker and see for yourself what DLLs an executable depends upon when launched.
Leave a comment:
-
Thank you Everyone
One more question related to Steve's response
If you have some reason for massive resources, putting them into DLLs would spread the load so it is more manageable for the calling executable.
say child1.dll , child2.dll and child3.dll each of which would load a portion of the original big program into memory.
Doing this way, it would be more efiicient in terms of memory allocation than having to execute one big program ?
The question is that :
If we have called say child2.dll and then close it and then go back to the MainProg.exe , will the memory of child2.dll
still persist after we have close up child2.dll ?
Are there additional memory clearance statements kinda similar to RESET and ERASE which we can use so that variables used in the DLLs are cleared
when we exit these DLLs ?
Leave a comment:
-
RE
If you have some reason for massive resources, putting them into DLLs would spread the load so it is more manageable for the calling executable. You will still run into absolute memory limits but if you are handling resources that big collectively you would load the start address of each DLL and dynamically load each one as you need it and free it after.
MCM
Leave a comment:
-
Tim,
Stack memory is assigned to an executable file, default in most is 1 meg but 2 or 4 meg are viable. You tend to increase the stack allocation if you are using recursion or run something that allocates a massive amount of LOCAL variables. Under Win32 on a 32 bit system, you can allocate collectively just under 2 gigabytes and if you use #option largemem32 you get another block of memory, 7 to 800 meg to operate on the first big allocation. On a 64 bit system you get a bit more with a 32 bit app. Virtual memory (IE: Disk emulation of memory) is used by the OS to swap out some apps memory so that more can be allocated in dynamic memory (RAM).
Leave a comment:
-
Originally posted by Tim Lakinir View PostI have seen somewhere in the forum, some members uses #STACK 4194304 statement
does this stack statement would be able to kinda stabilize the available virtual memory to load a large file from the resource
You may be able to get a larger file with #OPTION LARGEMEM32 directive:
"For 32-bit Windows applications, this option sets the "Large Memory Model" flag. This allows your application to use more than the original limit of 2 Gigabytes of memory. Depending upon the version of Windows in use, and the installed memory, the exact increase may vary from computer to computer. In most cases, you will likely be limited to a total of approximately 3 Gigabytes".
Leave a comment:
-
Thanks to all, except that in https://forum.powerbasic.com/forum/u...454#post771454
Under Win/32, the number of processes which may each use 2 GB memory is limited only by the total available VIRTUAL memory on the system, which is the amount of installed RAM plus the max size of the swap file.
does this stack statement would be able to kinda stabilize the available virtual memory to load a large file from the resource, see
https://forum.powerbasic.com/forum/u...645#post796645
Leave a comment:
-
If you have some reason for massive resources, putting them into DLLs would spread the load so it is more manageable for the calling executable. You will still run into absolute memory limits but if you are handling resources that big collectively you would load the start address of each DLL and dynamically load each one as you need it and free it after.
Leave a comment:
-
Originally posted by Tim Lakinir View Post
By the way, what would be the maximum amount of data that can be stored in a resource? I believe it is around 2GB ?
Leave a comment:
-
Originally posted by Michael Mattias View Post
Not that it matters because I would NEVER (on purpose) create two resources of same type with same ID but...
How do you access a resource by ordinal? I cannot find any WinAPI functions which do that. I only have reference thru Win/XP here so maybe there is a new function(?)
MCM
Within your application, just use Loadmage or whatever. In the case of a bitmap/icon/cursor:
If the image resource is to be loaded by ordinal from the module, use the MAKEINTRESOURCE macro to convert the image ordinal into a form that can be passed to the LoadImage function.
Leave a comment:
-
The actual amount of data is about 350k of RTF format text and this seems to be the problem.
Leave a comment:
-
FWIW: If there are duplicate Resource name/ID for the same type of resource, both resources get compiled, either one may be accessed by ordinal number but only the first by ID. If you have two different types of resources with the same name/id both may be accessed by name/id.
How do you access a resource by ordinal? I cannot find any WinAPI functions which do that. I only have reference thru Win/XP here so maybe there is a new function(?)
MCM
Leave a comment:
-
What surprised me was that it ran when it tried to write to memory that was not allocated by the app. Normally you get a GP fault with an error of that type. It was a pain to isolate because of that. Once I found the line by narrowing down where the error occurred, the rest was reasonably straight forward. Some of the innards of Windows still fascinates me.
Leave a comment:
-
Originally posted by Michael Mattias View PostFor that matter, if you built your executable with duplicate IDs for type RCDATA resources using '#RESOURCE' statements, that should* have been caught at compile time.
MCM
* should does not mean "does" .. I have found a number of PB intrinsics which don't always return a PB error.
Leave a comment:
Leave a comment: