Announcement

Collapse
No announcement yet.

Loading and using a Resource within a DLL

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Jim McLachlan
    replied
    Back again with good news! Thank you both for your help with this. Dale, as an FYI, I stated in my original post that I don't have any access to the routines in the EXE, so unfortunately your suggestion won't help me. I did learn that, at least for the RcData, I can fully control of every aspect of storing a resource in a DLL and also making use of it from within the same DLL. I also discovered along the way, that I can make use of a resource that resides in a different DLL, which I thought was very cool, and I have documented how to do that below.

    Here is the working code for the EXE, same as in my prior post above:
    Code:
    #COMPILE EXE
    DECLARE SUB MyProc LIB "My.DLL" ALIAS "MyProc" ( )
    ' --------------------------------
    FUNCTION PBMAIN () AS LONG
        MyProc()
    END FUNCTION
    ' --------------------------------

    Here is the working code for the DLL. Biggest changes from how it works in an EXE are:
    1. using a character label for the resource versus numeric
    2. getting the instance handle from LIBMAIN()
    3. calling a number of other functions to get the address of the resource instead of using RESOURCE$()
    Note: no error checking here.
    Code:
    $COMPILE DLL
    $INCLUDE "WIN32API.INC"
    #RESOURCE RCDATA, myg , "My.BMP"
    DECLARE SUB MyProc LIB "My.DLL" ALIAS "MyProc" ( )
    
    GLOBAL hInst AS DWORD
    
    ' --------------------------------
    
    FUNCTION LIBMAIN( BYVAL hInstance AS LONG, _
                      BYVAL fwdReason AS LONG, _
                      BYVAL lpvReserved AS LONG) AS LONG
    
        IF fwdReason = %DLL_PROCESS_ATTACH THEN
            hInst = hInstance
        END IF
    
        FUNCTION = 1 ' everyone is happy
    
    END FUNCTION
    
    ' --------------------------------
    
    SUB MyProc() EXPORT
    
        LOCAL ResourceString AS STRING
        ResourceString = RESOURCE$( RCDATA, "myg" )
        MSGBOX "Length: " + TRIM$(LEN(ResourceString)) ' This does not work
                                                       ' Replace with code below
    
        LOCAL hModule    AS DWORD
        LOCAL hFind      AS DWORD
        LOCAL ResHandle  AS DWORD
        LOCAL ResSize    AS DWORD
        LOCAL DataAddr   AS DWORD
        LOCAL MyString   AS STRING
    
        hModule   = hInst ' = LoadLibrary("Your.DLL") if resource is located in a different DLL from this one
        hFind     = FindResource(hModule,"myg", BYVAL %RT_RCDATA)
        ResSize   = SizeOfResource(hModule,hFind)
        ResHandle = LoadResource(hModule, hFind)
        DataAddr  = LockResource(ResHandle)
        MyString  = PEEK$(DataAddr, ResSize)
    
        MSGBOX "Inst: "      + TRIM$(hInst)
        MSGBOX "hModule: "   + TRIM$(hModule)
        MSGBOX "hFind: "     + TRIM$(hFind)
        MSGBOX "ResSize: "   + TRIM$(ResSize)
        MSGBOX "ResHandle: " + TRIM$(ResHandle)
        MSGBOX "DataAddr: "  + TRIM$(DataAddr)
        MSGBOX "Length: "    + TRIM$(LEN(MyString))
    
    END SUB
    ' --------------------------------
    Note that prior to the end of MyProc(), I wrote MyString to disk and compared it bit by bit with the original file and they are identical. Yippee!
    I did read that SizeOfResource() may not be entirely accurate but so far it has worked for me. I'll skin that cat at some other time.

    Leave a comment:


  • Jim McLachlan
    replied
    West coast here so just logging in. Thanks guys! Extra points to Dave for linking to Stuart's post, haha! I'll follow up with my final code once I get it working. So far I am getting the wrong length for the resource itself, but obviously I am way closer. I guess I need to study those code examples closer.

    Leave a comment:


  • Dave Biggs
    replied
    Thought the topic rang a bell See here too

    Leave a comment:


  • Stuart McLachlan
    replied
    Apparently a known problem:

    https://forum.powerbasic.com/forum/u...ource-question

    Specifically post #9 in that thread:
    Wasn't explicitly stated, but I think what people are saying is many (possibly all but RCData) resources work fine from a DLL. RCData does not using Resource$.
    ...
    Short summary (I think)
    • All #Resource statements are stored in a DLL.
    • RcData resources are not retrievable using Resource$, api code I posted is apparently close to what PB does, just with a module reference.
    • Several other PB methods of retrieving resources work fine from a dll.

    Leave a comment:


  • Stuart McLachlan
    replied
    This doesn't work either. IIt returns the correct length for the STRING resource, but not for the RCDATA


    $COMPILE DLL "My.DLL"
    #RESOURCE STRING, 112, "YourWideText"$$
    #RESOURCE RCDATA, 937 , "My.BMP"
    DECLARE SUB MyProc LIB "My.dll" ALIAS "MyProc" ( )
    ' --------------------------------
    SUB MyProc EXPORT

    LOCAL ResourceString AS STRING

    ResourceString = RESOURCE$(STRING,112)
    MSGBOX "Length: " + TRIM$(LEN(ResourceString))
    ResourceString = RESOURCE$( RCDATA,937 )
    MSGBOX "Length: " + TRIM$(LEN(ResourceString))
    END SUB
    ' --------------------------------

    Leave a comment:


  • Stuart McLachlan
    replied
    >'ResourceString = RESOURCE$ (RCDATA, "#937") 'Try this before other changes I made.

    I tried that, but it didn't make any difference, I get 0 as well.

    Leave a comment:


  • Dale Yarker
    replied
    create the string in EXE and pass to SUB in DLL. In DLL string is populated from resource, and STRPTR is put at location passed (the byref which is the VARPTR for the string) ((the zero length in DLL might be fixed with # and two DQs))

    Code:
     
    $COMPILE DLL #RESOURCE RCDATA, 937 , "My.BMP" ' -------------------------------- SUB MyProc ALIAS "MyProc" (BYREF ResourceString AS STRING) EXPORT 'can skip DECLARE in 'DLL with alias here ResourceString = RESOURCE$( RCDATA, 937 ) 'ResourceString = RESOURCE$ (RCDATA, "#937") 'Try this before other changes I made. MSGBOX "Length: " + TRIM$(LEN(ResourceString)) END SUB ' --------------------------------
    Code:
     
    #COMPILE EXE DECLARE SUB MyProc LIB "My.dll" ALIAS "MyProc" (BYREF A_Str AS STRING) ' -------------------------------- FUNCTION PBMAIN () AS LONG LOCAL MyStr AS STRING MyProc(MyStr) END FUNCTION ' --------------------------------

    Leave a comment:


  • Jim McLachlan
    started a topic Loading and using a Resource within a DLL

    Loading and using a Resource within a DLL

    I read some older posts about this but they were many years old and prior to RESOURCE$() so here goes...

    I don't have any control of a particular EXE but I do have control of a DLL that contains functions called by code within the EXE. When one of the functions in the DLL is called, I want it to be able to use a particular resource that I have compiled into the DLL, but I am not having any success. I have tested the code compiled in a sample EXE and it works, so I am at a loss at this point. Any advice would be most appreciated.

    Here is the sample EXE code I used to test my loading and retrieving of the resource. It yields the correct length when displayed by MSGBOX():
    Code:
    #COMPILE EXE
    #RESOURCE RCDATA, 937 , "My.BMP"
    ' ---------------------------------
    FUNCTION PBMAIN () AS LONG
    
        LOCAL ResourceString AS STRING
        ResourceString = RESOURCE$( RCDATA, 937 )
        MSGBOX "Length: " + TRIM$(LEN(ResourceString))
    
    END FUNCTION
    ' ---------------------------------
    Here is the same code in my DLL code that yields 0 for the length displayed by MSGBOX() when MyProc is called by some calling code in an EXE
    Code:
    $COMPILE DLL
    
    #RESOURCE RCDATA, 937 , "My.BMP"
    DECLARE SUB MyProc LIB "My.dll"  ALIAS "MyProc" ( ) 
    ' --------------------------------
    SUB MyProc EXPORT
    
    LOCAL ResourceString AS STRING
    ResourceString = RESOURCE$( RCDATA, 937 )
    MSGBOX "Length: " + TRIM$(LEN(ResourceString))
    
    END SUB
    ' --------------------------------

    Sample EXE for the above DLL would be:
    Code:
    #COMPILE EXE
    DECLARE SUB MyProc LIB "My.dll" ALIAS "MyProc" ( )
    ' --------------------------------
    FUNCTION PBMAIN () AS LONG
    
    MyProc()
    
    END FUNCTION
    ' --------------------------------
Working...
X