Compiling to DLL

Started by Martin Francom, February 12, 2010, 10:58:09 PM

Previous topic - Next topic

Martin Francom

Paul,
   Can you explane the do's and don'ts of this new feature:
Quote
- 0000697: [New Feature Request] Allow DLL FireFly projects (similar to FireFly Version 2) (Paul Squires) - closed.

Can child forms for the main program be put in the DLL and then called by the main program?

I assume a FF3 DLL  should not contain a FrmMAIN  but it can have popup forms and child forms that can be called by the main program.  Correct?



Paul Squires

Quote from: Marty Francom on February 12, 2010, 10:58:09 PM
Can child forms for the main program be put in the DLL and then called by the main program?

Yes, similar to FF2. Create your Forms and set the "Export" property for the Form to "True". You would then create a Declare statement in your main exe code to call the _Show function of the Form in the dll.

Quote
I assume a FF3 DLL  should not contain a FrmMAIN  but it can have popup forms and child forms that can be called by the main program.  Correct?
Correct.

Paul Squires
PlanetSquires Software

Martin Francom

This feature may come in handy for large projects like the one I am currently working on.  I never used the FF2 version of this feature.  So I am interested on how this works.

Joakim Schramm

#3
Hi guys,

may I chip in on this threed as well? I have a dll with a form that compiled in FF2 and it then worked fine to call that dll's form from VB6 but after compiling the same dll in FF3 (after successfull import) I now get a GPF when calling the form in dll. As I just (re-)upgraded to FF3 (after Paul took the great decision to reimplement DLL project) I haven't had time yet to go through everything, so wonder if there is anything particullary "sensitive" that have changed between FF2 and FF3 regarding forms?

I had missed the export property, but GPF remains also after setting it to True. It's late here now so will continue exploring tomorrow but just thought if there might be something "obvious" I have missed in the the FF2 to FF3 transition? I also just upgraded to PB9 but I doubt that could be the problem although one never knows, so I will test compiling with PB8.04 as well tomorrow.

I know this is a PB and not a VB type of forum, but my app is too big to easily convert to PB, so I'm taking it gradually cutting down on VB code by moving it to PB dll's. So I hope this is ok as "on the stack" this all about Basic programing ;-)

My VB6 declaration looks like this
Declare Function ViewAtlas Lib "acjAtlasEx.DLL" (ByVal hParentForm As Long, StrCountry As String) As String


and I call it like this in a button click event
Dim sRecord As String
Dim sLocation As String

sLocation = txtPlace.Text & ":" & cboCountry.Text
sRecord = ViewAtlas(Me.hWnd, sLocation)


In FF3 I then has this code
Function ViewAtlas Alias "ViewAtlas" (ByVal hParentForm As Long, StrCountry As String) Export As String
Local nReturn As Long
Local StrReturn As String * 94

sCapText = GetString(28)

sInfoText = GetString(29) + $CrLf + $CrLf + GetString(30) + $CrLf + $CrLf + GetString(31) + $CrLf + $CrLf + GetString(32)

CurrPlace = Extract$(1, StrCountry, ":")
CurrCountry = Remain$(1, StrCountry, ":")

nReturn = FRMATLASVIEW_Show(hParentForm,%TRUE, 1&)
'MsgBox "CurrCountry " & CurrCountry ,,"DEBUG"
If nReturn Then
   Type Set StrReturn = uCurrPlace
   Function = StrReturn
Else
   Function = ""
End If   

End Function


while I (at least for now) wont post the full form code, this simple example is enough to trigger the GPF (everything else taken out), code runs fine up to the call to FRMATLASVIEW_WM_CREATE though.
Function FRMATLASVIEW_WM_CREATE ( _
                                hWndForm As Dword, _  ' handle of Form
                                ByVal UserData As Long _  'optional user defined Long value
                                ) As Long
Local Result As Long 
Local NewIndex As Long
Local sRecord, sKey, sPlace As String

  MsgBox "DEBUG " ,,"DEBUG"
End Function


So just by creating the form seem to be enough causing the GPF.

You talk about the _Show function Paul but I don't seem to be able finding any in my (from FF2 converted) form. I also tried to remove the WM_CREATE function in hope it would be recreated (with proper arguments) when I selected the form in code windows left drop down (like in VB6 IDE) but instead it simply jump to select another function of one of the controls that lives on the form, so now sure what's going on here?

EDIT: Stupid me, I call the forms _Show function in my exported ViewAtlas function but well GPF remains...

Paul Squires

Not sure what the GPF would be at this stage. I don't have VB installed anymore so I can not test it.

I did create a one form DLL project and exported the Form1. I then created a simple PB exe to display the Form in the DLL:


#Compile Exe

Declare Function FORM1_Show Lib "Project1.dll" ( ByVal hwndParent As Dword, _
                             ByVal ShowModalFlag As Long, _
                             ByVal UserData As Long _
                             )  As Long

Function PBMain() As Long

    FORM1_Show 0, 1, 1
   
End Function


As a test, I wonder if you can display the Form in VB directly rather than going through your ViewAtlas function:



Declare Function FRMATLASVIEW_Show Lib "Project1.dll" Alias "FRMATLASVIEW_SHOW" ( ByVal hwndParent As Long, _
                             ByVal ShowModalFlag As Long, _
                             ByVal UserData As Long _
                             )  As Long

... in your Button Click event:

    FRMATLASVIEW_Show Me.hWnd, 1, 0
   

Paul Squires
PlanetSquires Software

Joakim Schramm

No, just get an error "Can't find DDL entry point FRMATLASVIEW_Show in acjAtlasEx.DLL" and then GPF

In VB this declare
Declare Function FRMATLASVIEW_Show Lib "acjAtlasEx.DLL" (ByVal hwndParent As Long, ByVal ShowModalFlag As Long, ByVal UserData As Long) As Long


and call in button click like this
Call FRMATLASVIEW_Show(Me.hWnd, 1&, 0&)


Export for form is True, although I realized in my original code I don't need it as the form never really is exported but used inside dll.

I ran a comparison with Beyond Compare, between FF2 and FF3 release folder and noticed quite many differances there. As I was smart this time and installed to other location then FF2 I have both old and new FF installed, so I will start over from scratsh and make a new comparison in a more prestine state. Obviously FF3 must do something differently that upset Windows. I tested with PB8 as well by the way, and no differance.

@ Marty: Sorry that I sort of hijacked your threed but I figured you basically had got your question answered and this should just built on top of the knowledge base for people coming later... So I hope you are ok with it mate?

Joakim Schramm

#6
Recompiled DLL project in FF2 using PB9.03 and confirmed it worked as expected. Copied the full FF2 project folder into where I have FF3 projects, opened it in FF3 and converted succesfully. As conversion leave old files in release (really needed as they are backed up in FF2_Backup anyway?) folder I emptied it. Compiled using PB9.03 and first observation is that dll compiled in FF3 is 12288 bytes smaller then when compiled in FF2!? It certainly looks as if something is left out?

The build files differs all as well, except for the .jfp file, I will try to desect the relevant parts as it would be too much to post, but in general all .inc files appear to have shrinked when compile in FF3

EDIT: Observation 2 (and this may be something), In FF2 project Startup Form/Function is set to FF_LibMain but in FF3 this is set to FF_AppStart. In the generated declares.inc both FF2/3 creates
Declare FUNCTION FF_LIBMAIN(BYVAL hInstance    AS LONG, _
                    BYVAL fwdReason    AS LONG, _
                    BYVAL lpvReserved  AS LONG) AS LONG


but I don't find any declare for FF_APPSTART, can it possibly be an ops here in the converstion of dll project? DLL does load though and only creating the form seem to cause problem.

Declare.inc is 1 of only 2 files, also main.bas, that actually is bigger then generated in FF2. It may not be of importance but just note it down here.

Joakim Schramm

Observation 3

Following up on previous post I wanted to see what values came up when creating a DLL project from start in FF3 and then notice it creates the module FF_DLLMain with
Function FF_LIBMAIN( ByVal hInstance    As Dword, _
                     ByVal fwdReason    As Long, _
                     ByVal lpvReserved  As Long _
                     ) As Long


      Select Case fwdReason

      Case %DLL_PROCESS_ATTACH
          ' Indicates that the DLL is being loaded by another process (a DLL
          ' or EXE is loading the DLL).  DLLs can use this opportunity to
          ' initialize any instance or global data, such as arrays.

          Function = 1   'success!
          'FUNCTION = 0   'failure!  This will prevent the DLL from running.

      Case %DLL_PROCESS_DETACH
          ' Indicates that the DLL is being unloaded or detached from the
          ' calling application.  DLLs can take this opportunity to clean
          ' up all resources for all threads attached and known to the DLL.

          Function = 1   'success!
          'FUNCTION = 0   'failure!

      Case %DLL_THREAD_ATTACH
          ' Indicates that the DLL is being loaded by a new thread in the
          ' calling application.  DLLs can use this opportunity to
          ' initialize any thread local storage (TLS).

          Function = 1   'success!
          'FUNCTION = 0   'failure!

      Case %DLL_THREAD_DETACH
          ' Indicates that the thread is exiting cleanly.  If the DLL has
          ' allocated any thread local storage, it should be released.

          Function = 1   'success!
          'FUNCTION = 0   'failure!

      End Select

End Function


In FF2 project I have similar FF_LibMain module with FUNTION FF_LIBMAIN and this module appear to not been brought over when the project was converted from FF2 to FF3. Well it has in a way, it's in the project file just as the one created on new project but it never show up and get a Tab in the editor GUI. One thing I notice here as well is that the argument data type differs somewhat between the one created by new FF3 DLL project and the one converted.

In New project it's
[FF_WINMAIN_START]
Function FF_LIBMAIN( ByVal hInstance    As Dword, _
                     ByVal fwdReason    As Long, _
                     ByVal lpvReserved  As Long _
                     ) As Long
...
End Function
[FF_WINMAIN_END]


while in converted it's
[FF_WINMAIN_START]
FUNCTION FF_LIBMAIN(BYVAL hInstance    AS LONG, _
                    BYVAL fwdReason    AS LONG, _
                    BYVAL lpvReserved  AS LONG) AS LONG
...
END FUNCTION
[FF_WINMAIN_END]


investigation continues...

Paul Squires

Hi Joakim,

I'll do investigation today as well and I'll post here my findings. I'll do a project in both FF2 and FF3 to see exactly where the code changed (and why). We'll get to the bottom of this soon. There must be some small thing that is different that is causing VB to choke on the code.
Paul Squires
PlanetSquires Software

Joakim Schramm

Sounds good and I will certainly not stop digging either ;-)

Found this little differance in project file as well between the a new dll project and the converted

[Objects]

TopTab=#FF_WinMain#|True|True|0|41


exists in new project and probably what makes it show up in the editor tab. Not sure if it will have inpact on compile though. I can of course try to simply paste it into my converted project file but don't really know what |True|True|0|41 stands for?

Paul Squires

Hi Joakim,

I found a few things that could be the trigger. Not 100% sure at this point:

- FF3 is generating a #Resource file reference whereas FF2 is not.
- The LibMain DWord vs. Long variable declaration that you noticed (although I can't see this being a big problem because they are both 32-bit integers).
- FF3 is initializing the common controls classes whereas FF2 is not.
The assignment of the App.hInstance in LibMain needs to be moved after the call to FLY_SetAppVariable.
- Using the PB Included vs. using Jose's includes (can't see this as being a problem either).

Maybe try commenting out the #Resource line and then try commenting out the code that initializes the common controls. You can then manually re-compile the DLL using PB9 and test it with VB.

Quote
[Objects]TopTab=#FF_WinMain#|True|True|0|41
Yes, that only makes it show up in the editor as a tab.
Paul Squires
PlanetSquires Software

Joakim Schramm

Quote from: TechSupport on February 16, 2010, 09:56:26 AM
Hi Joakim,

I found a few things that could be the trigger. Not 100% sure at this point:

- FF3 is generating a #Resource file reference whereas FF2 is not.
- The LibMain DWord vs. Long variable declaration that you noticed (although I can't see this being a big problem because they are both 32-bit integers).
- FF3 is initializing the common controls classes whereas FF2 is not.
The assignment of the App.hInstance in LibMain needs to be moved after the call to FLY_SetAppVariable.
- Using the PB Included vs. using Jose's includes (can't see this as being a problem either).

Maybe try commenting out the #Resource line and then try commenting out the code that initializes the common controls. You can then manually re-compile the DLL using PB9 and test it with VB.
Hmm how would I do that in a simple way? I can just admit I am stupid on that as I been so spoiled to let FF do it for me, specially as main portions of my projects still are in VB6 I simple haven't got that "serious" with PB, yet. I probably did it at the time when I first purchased PB8, but too much time has since been spent in VB6 pleasurous IDE ;-) so can you give a one liner or something? The code editing is no problem, there I am at home.

If that wont show it I am thinking of rebuilding the project from start in FF3 and just copy in my code and see if that works. A compare between the 2 sets of generated files should then pretty much make it stick out I think.


Joakim Schramm

Quote from: TechSupport on February 16, 2010, 09:56:26 AM
- FF3 is generating a #Resource file reference whereas FF2 is not.

That's not correct by the way, FF2.99 at least does it.

Joakim Schramm

Sorry, I'm an idiot, common ctrl init commented out and dll recompiled but problem remain so that's obviously not it.

Joakim Schramm

Tried all your suggestions now but without success, so now I will rebuild the project as a new DDL project, rebuild form etc. and just copy in my code and see if that helps. It probably will turn out in the end just being because one small little tiny, but very important, detail.

I love computers and programming - it will keep me young forever!  ;D