Recent

Author Topic: DYLIB Cannot Add Requirement LCL/LCLBase  (Read 3378 times)

kevin.black

  • Full Member
  • ***
  • Posts: 121
DYLIB Cannot Add Requirement LCL/LCLBase
« on: February 19, 2019, 12:59:22 am »
I have a couple of issues WRT packages (and finding them) and did not want to conflate.

I have several DYLIBs that I'm converting from FMX. The DYLIBs require some of the functions that are in the FORMS unit and (say) in the Dialogs unit. Basically I need access to the LCL/LCLBase.

When I try to ADD a requirement to the DYLIB, both the LCL and LCLBase units are RED (supposedly offline). Further, even though INDY 10 is installed, I cannot add Indy as a Requirement either (so none of the INDY units are found) see attached image.

This is clearly not the case, ie. LCL/LCLBase/INDY are all installed, but I cannot ADD the LCL/LCLBase/INDY and the Dialogs Unit (for example) is not found, likewise any of the INDY iunits.

As a hack, I could try to add a dummy unit/form to the DYLIB, but that just seems a bit naff.

Any ideas how I might add these units (LCL/LCLBase) to my DYLIBs?

Kevin
« Last Edit: February 19, 2019, 01:13:52 am by kevin.black »

kevin.black

  • Full Member
  • ***
  • Posts: 121
Re: DYLIB Cannot Add Requirement LCL/LCLBase
« Reply #1 on: February 20, 2019, 12:58:35 am »
The dummy unit/form did not help, I could still NOT add LCL/LCLBase/LazIndy to my DYLIB. I assume also that I need Interfaces if I want to display a message box (since Lazarus needs to know which widget set to use).

So NO REPLIES?

ANYONE?

My Hack:

I have manually edited the LPI file to include the Requirements I want. This 'seems' to work, but I do not know whether this is acceptable or will fail/break at some point, ie. is there a reason I CANNOT / SHOULD NOT add LCL/LCLBase/LazIndy to a DYLIB?
Code: Pascal  [Select][+][-]
  1.     <RequiredPackages Count="4">
  2.       <Item1>
  3.         <PackageName Value="LCL"/>
  4.       </Item1>
  5.       <Item2>
  6.         <PackageName Value="LCLBase"/>
  7.       </Item2>
  8.       <Item3>
  9.         <PackageName Value="laz_synapse"/>
  10.       </Item3>
  11.       <Item4>
  12.         <PackageName Value="indylaz"/>
  13.       </Item4>
  14.     </RequiredPackages>

Kevin

Cyrax

  • Hero Member
  • *****
  • Posts: 836
Re: DYLIB Cannot Add Requirement LCL/LCLBase
« Reply #2 on: February 20, 2019, 01:27:54 am »
Which version of Lazarus you are using?

I don't know about unix dynamic link libraries, but on Windows there will be problems when you combine usage of LCL and dynamic link library.

https://docs.microsoft.com/en-us/windows/desktop/dlls/dllmain (See the warning box.)

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11382
  • FPC developer.
Re: DYLIB Cannot Add Requirement LCL/LCLBase
« Reply #3 on: February 20, 2019, 07:03:56 am »
Probably indy depends on of the LCLs, and that one is disallowed since having two copies of the LCL (one in the dylib, one in the main program) is non functional.

But that is just a guess.

kevin.black

  • Full Member
  • ***
  • Posts: 121
Re: DYLIB Cannot Add Requirement LCL/LCLBase
« Reply #4 on: February 21, 2019, 12:45:00 am »
Firstly let me say thank you for responding and that i am not trying to @Cyrax,

The DYLIBs I'm trying to get working are all ported from Delphi DLLs. There is nothing I'm trying to implement that isn't already functioning under windows. Your reference (it's a 2006 article) makes comment mainly about DLLMAIN which is a Windows only construct that I now don't use because it is not cross-platform (I used to use it, but now just use the units initialize and finalize sections orI have also coded same with an initialise function, ie. as you authenticate (say) via a function within the DLL - the first thing it does is perform initialise, a number of ways to skin that cat and this relies on absolutely nothing special, ie. it doesn't need DLLMAIN to function and doesn't need any initialze/finalize construct). FWIW I do exactly what the referenced article recommends in initialize, ie:
Quote
The following tasks are safe to perform within DllMain:
Initialize static data structures and members at compile time.
Create and initialize synchronization objects.
Allocate memory and initialize dynamic data structures (avoiding the functions listed above.)
Set up thread local storage (TLS).  <-----NOPE
Open, read from, and write to files.
Call functions in Kernel32.dll (except the functions that are listed above).  <----NOPE
Set global pointers to NULL, putting off the initialization of dynamic members.

In Microsoft Windows Vista™, you can use the one-time initialization functions to ensure that a block of code is executed only once in a multithreaded environment.  <-----As you can with the Initialize section or with an initialize function
There is nothing in that best practice that says a DLL cannot react with the environment.

@marcov,

It isn't/does not appear to be an issue with Delphi and DLLs in Windows. You can access the RTL and units like Forms, Dialogs etc. For example (and yes I know some say you should never use it) FMX Application.Processmessages is in the Forms unit. Unless you have access to that unit then you do not get the Application Object. And the Dialogs unit?, without that you cannot even do a showmessages so your DLL becomes hermetically sealed.

I use the DLL(s) to perform such things as Authentication (which needs to pop a web browser), provide an alert system (which accesses the Windows message pump and some other construct on the OSX side) and to update various Drive status (using callbacks). The DLL(s) are called by other (C++) DLLs and by other Delphi and C++ Programs. To that end the only parameters in/out are pChars, booleans and integers. They all function fine in the Windows World.

So you suggest that the issue is that access to the LCL seems prohibited? As noted, in the Delphi world that isn't an issue. Windows seems to think that's OK as well (for example the dialog Comdlg32 DLL which clearly interacts with the outside world, and SnapIns for example use DLLs to store UI).

So it seems that it is common practice for DLLs (and I assume DYLIBs) to interact with the environment and to do that with Lazarus/FPC then the software needs access to the various units that provide access (Forms, Dialogs, Interfaces etc etc) so why would LCL and LCLBase not be accessible? And, if like you say LazIndy uses the LCL then it is shown as RED when I try to add the requirement, I can Add TMSLCLCloudPackPkg - this is a commercial package that does similar things (REST access to cloud services - and use the Forms/Dialogs/etc units) and I can add that as a requirement. To me, it seems like there is a BUG in the Requirements add routine. It shows LCL/LCLBase/LazIndy as being ONLINE (ie. not installed). Look at the attached image, see the packages that are supposedly ONLINE, but are actually local. And look at the many other packages that are local and would require integration with the outside world.

I'm not suggesting you ate wrong, I'm just suggesting it doesn't make any sense to me given what DYLIBs and DLLs do actually do and what packages are and are not available. What is the criteria for the system deciding that a package is local or online, the logic escapes me.

And, of course when you try to install the 'ONLINE' package, there is nothing there to install (because it is already installed), see second image.

So I guess, without any definitive solution, all I can do is try to get my DLIB to function using the hack mentioned in my earlier post by editing the LPI file directly.

Yours in confusion,
Kevin

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11382
  • FPC developer.
Re: DYLIB Cannot Add Requirement LCL/LCLBase
« Reply #5 on: February 21, 2019, 03:15:41 pm »
It is forbidden in Delphi too, there is a reason why Delphi has
packages.

Sharemem is a mitigation for some of it though

Read e.g. http://wiki.freepascal.org/packages for background

balazsszekely

  • Guest
Re: DYLIB Cannot Add Requirement LCL/LCLBase
« Reply #6 on: February 23, 2019, 01:29:20 pm »
@kevin.black

Finally I upgrated to Mojave. Is it me or macOS is getting increasingly annoying with each new release? Anyways after installing Lazarus Trunk/FPC fixes3.2, the IDE works, but is very unstable. If I open random IDE window, an access violation dialog appears, luckily the ignore strategy works, after clicking "OK" I can continue working. The annoying fppkg issue won't go away even after I delete the config folder inside .fppkg directory. As a conclusion cocoa has improved a lot lately, but is still not stable enough in my opinion. The good new is I was able to reproduce and partially fix(r 60472) the issues with the packages. Please do the following:
1. Get lazarus trunk again wit fpcupdeluxe
2. Uninstall OPM
3. Rebuild IDE

You should be able to add LCL, LCLBase(as in the attached screenshot) to the requirement list.
« Last Edit: February 23, 2019, 01:32:14 pm by GetMem »

kevin.black

  • Full Member
  • ***
  • Posts: 121
Re: DYLIB Cannot Add Requirement LCL/LCLBase
« Reply #7 on: February 25, 2019, 03:15:32 am »
@marcov,

Sharemem is a mitigation for some of it though

Read e.g. http://wiki.freepascal.org/packages for background
Firstly I appreciate the response. Secondly I read the reference, to me it was a bit confusing and non-definitive. For example
Quote
So most likely it works as follows:
the system unit inits first, and must be (kept) hardened so that plugin units (like other memmanagers) can plug in. (it already is)
Then units are inited in normal order as would it be a whole program, but a package initializes fully when the first unit would initialize.
_OR_ I'm dead wrong about packages initializing as a whole.
is a bit vague.

So, that would be great if everything was in the Delphi/Lazarus world. The point of me writing DLLs/DYLIBs is that others can use them. AFAIK (and I profess not to be an expert) sharemem is NOT an option if your DLL is being called by an external C++ application/DLL/DYLIB, there is no way that external entity can have any understanding of the shared memory of your DLL. And I'm not entirely sure that those external entities have access to Delphi/Lazarus packages, I could, of course, be wrong. In the case of say a Lazarus package, can you point me to an example of a lazarus package that has functions callable by an external C++ application or DLL/DYLIB, I would be interested to see how to code them?

I am very careful in the types that pass between the DLLs/DYLIBs I build, they are pChar/pWideChar, boolean, integer - that's it. So far in the Delphi world on Windows I have had absolutely no problems (other than those of my own making).

Can you please give a reference where use of say Forms, Dialogs, etc units are forbidden to be used in Delphi? For example Embarcadero documentation states:
Quote
For most applications, packages provide greater flexibility and are easier to create than DLLs. However, there are several situations where DLLs would be better suited to your projects than packages:

1. Your code module will be called from non-Delphi applications.  <<<<<-----Yes that's me
2. You are extending the functionality of a Web server.
3. You are creating a code module to be used by third-party developers.    <<<<<-----Yes that's me
I cannot see where access to the VCL/FMX libraries are forbidden. Looking around there appears to be many examples of where a DLL needs to communicate with it's environment and so FORMS/DIALOGS units (for example) are used.

@Getmem,

Thank you for doing that, first thing on my agenda (after getting a caffeine hit). Appreciate you looking into my issue in the first place, appreciate the time spent in coming up with a solution, it is/will be a big help to me.

EDIT:Just to confirm, worked perfectly - see image, thanks again.

Regards,
Kevin
« Last Edit: February 25, 2019, 03:39:18 am by kevin.black »

 

TinyPortal © 2005-2018